Modular Arithmetic
Authors: Darren Yao, Michael Cao, Andi Qu, Benjamin Qi, Andrew Wang
Prerequisites
Working with remainders from division.
Resources | |||
---|---|---|---|
IUSACO | very brief, module is based off this | ||
David Altizio | plenty of examples from math contests | ||
CPH | |||
PAPS | |||
CF | some practice probs | ||
MONT |
Introduction
In modular arithmetic, instead of working with integers themselves, we work with their remainders when divided by . We call this taking modulo . For example, if we take , then instead of working with , we use . Usually, will be a large prime, given in the problem; the two most common values are and . Modular arithmetic is used to avoid dealing with numbers that overflow built-in data types, because we can take remainders, according to the following formulas:
Modular Exponentiation
Focus Problem – read through this problem before continuing!
Resources
Resources | |||
---|---|---|---|
cp-algo |
Binary exponentiation can be used to efficently compute . To do this, let's break down into binary components. For example, = = . Then, if we know for all which are powers of two (, , , , , we can compute in .
To deal with , observe that modulo doesn't affect multiplications, so we can directly implement the above "binary exponentiation" algorithm while adding a line to take results .
Solution - Exponentiation
Solution
Modular Inverse
The modular inverse is the equivalent of the reciprocal in real-number arithmetic; to divide by , multiply by the modular inverse of . We'll only consider prime moduli here.
For example, the inverse of modulo is . This means that for any integer ,
For example, .
Resources | |||
---|---|---|---|
cp-algo | Various ways to take modular inverse, we'll only discuss the second here |
With Exponentiation
Fermat's Little Theorem (not to be confused with Fermat's Last Theorem) states that all integers not divisible by satisfy . Consequently, . Therefore, is a modular inverse of modulo .
C++
int main() {ll m = 1e9+7;ll x = binpow(2,m-2,m);cout << x << "\n"; // 500000004assert(2*x%m == 1);}
Java
public class main{public static void main(String[] args) throws IOException{long m = (long)1e9+7;long x = binpow(2,m-2,m);System.out.println(x); // 500000004assert(2*x%m == 1);}}
Because it takes time to compute a modular inverse modulo , frequent use of division inside a loop can significantly increase the running time of a program. If the modular inverse of the same number(s) is/are being used many times, it is a good idea to precalculate it.
Also, one must always ensure that they do not attempt to divide by 0. Be aware that after applying modulo, a nonzero number can become zero, so be very careful when dividing by non-constant values.
We can also use the extended Euclidean algorithm. See the module in the Advanced section.
Templates
Resources | |||
---|---|---|---|
Benq | |||
Benq | feasible to type up during a contest |
Using my template, both of these do the same thing:
int main() {{int a = 1e8, b = 1e8, c = 1e8;cout << (ll)a*b%MOD*c%MOD << "\n"; // 49000000}{mi a = 1e8, b = 1e8, c = 1e8;// cout << a*b*c << "\n"; // doesn't work// ^ not silently converted to intcout << int(a*b*c) << "\n"; // 49000000}}
Problems
Status | Source | Problem Name | Difficulty | Tags | Solution | URL |
---|---|---|---|---|---|---|
CSES | Easy | Show Tagsmodular arithmetic | External Sol | |||
CF | Easy | Show Tagsmodular arithmetic | Check CF | |||
CSES | Normal | Show Tagsmodular arithmetic |
Module Progress:
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!