Modular Arithmetic
Modular Arithmetic
Modulus Operator
If a % b = c , then it can also be written as a ≡ c mod(b), which says a will give remainder of c when
divided by b. Eg: 7 % 3 = 1 can also be written as 7 ≡ 1 mod(3)
Ideally, if we look according to periodicity, then it should have been 2 only as we always consider
range of expression a % b from 0 to (b-1).
But C++ treats modulus in a different way, i.e. C++ treats -a % b as -(a % b)
C++ is not so good at handling negative things, it treats even ((-a) % (-b)) as -(a % b)
Thatswhy, we don't deal much with negative numbers in modulo part.
Modulo Arithmetic
Thatswhy, sometimes different coding platforms ask you to return ans % p instead of directly
returning ans, where p is any random number. They do so to shorten the range of answer in [0, p − 1].
Example :
A set S contains 'n' elements. If A and B are subsets of set S, then find number of different
combinations of A & B generated such that A ∩ B = ∅.
Since, each element in Set S has 3 options: either go to A, or to B, or no where. So, the total number
of different combinations of A & B would be 3 . But the problem is 3 becomes large very very fast, so
n n
Significance of using 10 9
+ 7 as Modulus
1. It's a Prime number
On using prime numbers as modulus, you get more diversified values as possible outputs.
To majorly avoid hard-coded solutions getting accepted.
So that Inverses would always exist.
2. It's the first prime after 10
9
3. Because on choosing 10 + 7 as modulus, sum of 2 remainders just fits in int range.
9
Note : If you take modulus of 2 numbers, then both of their remainders would be around at maximum
of 10 , and if you multiply both of them then the result would be around 10 which will not fit in the
9 18
integer range. So whenever something around multiplication comes, you have to use long long
datatype.
Example - 1
It is currently 7:00 PM. What time (in AM or PM) will it be in 1000 hours ?
Example - 2
Calculate the value of expression (a + b − c × e d
+ f) mod (10
9
+ 7)
If the intermediate values are negative, then that's not wrong, it's just that we should've printed their
positive counter part.
For example, let's consider expression
(3 × −4) mod 5
If it stayed as it is,
They're still both are the same thing, you just not have corrected -2 to be 3 in realm of (mod 5)
-2 and 3 are same thing in realm of (mod 5). So, it's just about correcting the final value, if you let the
intermediate value be negative and still not overflow, then that's fine.
So, to get the positive counter part, while printing do (ans mod m + m) mod m
#include<bits/stdc++.h>
using namespace std;
signed main() {
int a, b, c, d, e, f;
cin >> a >> b >> c >> d >> e >> f;
int ans = 1;
for(int i=0; i<d; i++) {
ans = (ans * e) % mod;
}
return 0;
}
Binary Exponentiation
Binary Exponentiation
It's a Algorithm that calculates a in O(log b) time complexity.
b
Intution :
b−1
⎧a × a if b is odd
b
a = ⎨
⎩
b/2 b/2
a × a if b is even
It's like mostly at every step we're doubling the power, infact in every 2 steps it will get half for sure
In 2 steps you're getting half, so in 2 × log n steps you will get to 1
Hence, it's time complexity is O(log n)
Code :
#include<bits/stdc++.h>
using namespace std;
signed main() {
int a, b;
cin >> a >> b;
return 0;
}
Note :
If there's modulo, we add modulo
Else, we don't add modulo
Inverses
Need of Inverses
Unlike addition, subtraction & multiplication, in case of division modulus(%) can't be broken down
a (a mod c)
( ) mod c ≠
b (b mod c)
Inverses
Let's assume value of above expression to be 'x'
a
x ≡ ( ) (mod c)
b
On multiplying both sides with 'b', maybe numbers won't match but their remainders will
(b × x) mod c ≡ a mod c
On putting a = 1, we get
1
x ≡ (mod c)
b
From above, we can say that there might be a possible value (i.e. x) which signifies 1
b
such that
(b × x) mod c ≡ 1 mod c
If we are able to find an x that satisfies above condition, then we will call that x as Inverse of b
This x is denoted as b −1
Example
Let's understand this with a numeric example,
−1
b ⋅ b ≡ 1 (mod 7)
So,
b 1 2 3 4 5 6
−1
b 1 4 5 2 3 6
Now,
4
( ) mod 7 = 2
2
4
−1
( ) mod 7 ≡ (4 ⋅ 2 ) mod 7
2
−1
(4 ⋅ 2 ) mod 7 = (4 ⋅ 4) mod 7 = 16 mod 7 = 2
So, when we're doing mod with certain fraction & if we're able to find inverse of number in
denominator, then at time of dividing, instead of dividing we will multiply with the number's inverse
b 1 2 3 4 5
−1
b 1 DNE DNE DNE 5
Note : This is one of the reasons that why the modulo's given in problems are always a prime number
(It's because prime number will always be co-prime with any other number). Thatswhy modulo's given
in the problems are prime numbers, so that Inverses always exists.
Note : Prime modulo is only needed for existence of inverses that are required in division operations,
but for any other operations (i.e. multiplication, addition & subtraction) modulo need not be prime
number.
Program for finding Inverse
Approach :
From Fermat's Little Theorem,
p−2
a ⋅ a ≡ 1 (mod p)
From Inverses,
−1
a ⋅ a ≡ 1 (mod p)
−1 p−2
a mod p ≡ a mod p
Example :
If we want 2 −1
in , then
mod 7
−1 7−1
2 = 2 mod 7 = 4
Code :
#include<bits/stdc++.h>
using namespace std;
int inverse(int x) {
return binpow(x, mod-2);
}
Rules of Inverses
−1 −1
a mod p ≡ (a mod p) mod p
x → (−∞, ∞)
x mod 4 → [−3, 3]
All we did was adding the number, and taking the remainder again
So, that can never change the answer because when you're taking remainder with x and if you
add x, then that doesn't change the answer
So, if the module had been m, then the final range would have been [0, m − 1]
5. Always use Binary Exponentiation or Loops, never use the pow() function of STL
Because :
pow() function calculates in floating-point
So, 5 can come out to be 25.000001 or 24.9999999 also
2