Compute binomial coefficient module prime p in C++ - c++

Problem statement: Compute the binonimal coefficient C(n,k) mod p. Here p is a prime.
I've done a bit of research online but I still don't understand why the following code works for this problem:
factorial[0] = 1;
for (int i = 1; i <= MAXN; i++) {//compute factorial
factorial[i] = factorial[i - 1] * i % m;
}
long long binomial_coefficient(int n, int k) {
return factorial[n] * inverse(factorial[k] * factorial[n - k] % m) % m;//I don't get it why we have to multiply with inverse(factorial[k] * factorial[n - k] % m)
}
I know the definition of modular inverse but i'm still confused how it can be relevant here. Can someone help me clarify this code ?

The factorial formula C(n, k) = n! / (k! (n-k)!) can be rewritten as C(n, k) k! (n-k)! = n!. Then:
taking mod p on both sides:  C(n, k) k! (n-k)! ≡ n! mod p;
multiplying by the modular inverse:  C(n, k) k! (n-k)! inverse(k! (n-k)!) ≡ n! inverse(k! (n-k)!) mod p;
simplifying a inv(a) = 1:  C(n, k) ≡ n! inverse(k! (n-k)!) mod p.
The latter is equivalent to C(n, k) mod p = ((n! mod p) (inverse(k! (n-k)!) mod p)) mod p.

Related

Calculate large multiplication and divide under modulus

In C++, I have a problem need to calculate ((a * b * c) / n) % m with large a, b and c (0 < a, b, c <= 10^9 and n, m > 0). And the problem guaranteed that a * b * c is divisible by n.
I tried calc ((a * b) % m * c) % m) / n but it's not a right answer.
Idea is to keep removing the common factors in numerator and denominator by calculating gcd and dividing it out. It is illustrated in following python code. In C++, gcd can be easily calculated using extended euclid's algorithm.
import math
def prod(a,b,c,n):
num = [a,b,c]
p = 1
tmp = n
for i in range(len(num)):
g = math.gcd(num[i],tmp)
num[i] /= g
tmp /= g
p = (p*num[i]) % n
return p

Raising a number to a huge exponent

I am given the number 3 and a variable 'n', that can be as high as 1 000 000 000 (a billion). I have to print the answer of 3^n modulo 100003. I tried the following:
I tried using the function std::pow(3,n), but it doesn't work for large exponents(can't apply the modulo during the process).
I tried implementing my own function that would raise the number 3 to the power n so I could apply the modulo when needed, but when tested with very large numbers, this method proved to be too slow.
Lastly I tried prime factorization of the number 'n' and then using the factors of 'n' (and how many times they appear) to build back the answer and this seems like the best method that I could come up with (if it is correct). The problem is what would I do for a huge number that is already prime?
So these were the ideas that I had, if anyone thinks there's a better way (or if one of my methods is optimal), I would appreciate any guidance.
Take advantage of property of modular arithmetic
(a × b) modulo M == ((a module M) × (b modulo M)) modulo M
By using above multiplication rule
(a^n) modulo M
= (a × a × a × a ... × a) modulo M
= ((a module M) × (a modulo M) × (a modulo M) ... × (a modulo M)) modulo M
Calculate the result by divide and conquer approach. The recurrence relation will be:
f(x, n) = 0 if n == 0
f(x, n) = (f(x, n / 2))^2 if n is even
f(x, n) = (f(x, n / 2))^2 * x if n is odd
Here is the C++ implementation:
int powerUtil(int base, int exp, int mod) {
if(exp == 0) return 1;
int ret = powerUtil(base, exp / 2, mod) % mod;
ret = 1LL * ret * ret % mod;
if(exp & 1) {
ret = 1LL * ret * base % mod;
}
return ret;
}
double power(int base, int exp, int mod) {
if(exp < 0) {
if(base == 0) return DBL_MAX; // undefined
return 1 / (double) powerUtil(base, -exp, mod);
}
return powerUtil(base, exp, mod);
}
This is to augment Kaidul's answer.
100003 is a prime number, which immediately casts in the Fermat's Little Theorem: any number raised to a prime power is congruent to itself modulo that prime. It means that you don't need to raise to n'th power. A n % 100002 power suffices.
Edit: example.
Say, n is 200008, which is 100002 * 2 + 6. Now,
3 ^ 200007 =
3 ^ (100002 + 100002 + 6) =
3 ^ 100002 * 3 ^ 100002 * 3 ^ 6
FLT claims that (3 ^ 100002) % 100003 == 1, and the last line above, modulo 100003, reduces to 3 ^ 6. In general, for a prime p,
(k ^ n) % p == k ^ (n % p)
Of course, it only speeds the computation if the exponent n is greater than p. As per your request (exponent 100, modulo 100003) there is nothing to reduce. Go straight to the Kaidul's approach.

Finding nCr%m in C++ efficiently for very large N [duplicate]

I want to compute nCk mod m with following constraints:
n<=10^18
k<=10^5
m=10^9+7
I have read this article:
Calculating Binomial Coefficient (nCk) for large n & k
But here value of m is 1009. Hence using Lucas theorem, we need only to calculate 1009*1009 different values of aCb where a,b<=1009
How to do it with above constraints.
I cannot make a array of O(m*k) space complexity with given constraints.
Help!
The binominal coefficient of (n, k) is calculated by the formula:
(n, k) = n! / k! / (n - k)!
To make this work for large numbers n and k modulo m observe that:
Factorial of a number modulo m can be calculated step-by-step, in
each step taking the result % m. However, this will be far too slow with n up to 10^18. So there are faster methods where the complexity is bounded by the modulo, and you can use some of those.
The division (a / b) mod m is equal to (a * b^-1) mod m, where b^-1 is the inverse of b modulo m (that is, (b * b^-1 = 1) mod m).
This means that:
(n, k) mod m = (n! * (k!)^-1 * ((n - k)!)^-1) mod m
The inverse of a number can be efficiently found using the Extended Euclidean algorithm. Assuming you have the factorial calculation sorted out, the rest of the algorithm is straightforward, just watch out for integer overflows on multiplication. Here's reference code that works up to n=10^9. To handle for larger numbers the factorial computation should be replaced with a more efficient algorithm and the code should be slightly adapted to avoid integer overflows, but the main idea will remain the same:
#define MOD 1000000007
// Extended Euclidean algorithm
int xGCD(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int x1, y1, gcd = xGCD(b, a % b, x1, y1);
x = y1;
y = x1 - (long long)(a / b) * y1;
return gcd;
}
// factorial of n modulo MOD
int modfact(int n) {
int result = 1;
while (n > 1) {
result = (long long)result * n % MOD;
n -= 1;
}
return result;
}
// multiply a and b modulo MOD
int modmult(int a, int b) {
return (long long)a * b % MOD;
}
// inverse of a modulo MOD
int inverse(int a) {
int x, y;
xGCD(a, MOD, x, y);
return x;
}
// binomial coefficient nCk modulo MOD
int bc(int n, int k)
{
return modmult(modmult(modfact(n), inverse(modfact(k))), inverse(modfact(n - k)));
}
Just use the fact that
(n, k) = n! / k! / (n - k)! = n*(n-1)*...*(n-k+1)/[k*(k-1)*...*1]
so you actually have just 2*k=2*10^5 factors. For the inverse of a number you can use suggestion of kfx since your m is prime.
First, you don't need to pre-compute and store all the possible aCb values! they can be computed per case.
Second, for the special case when (k < m) and (n < m^2), the Lucas theorem easily reduces to the following result:
(n choose k) mod m = ((n mod m) choose k) mod m
then since (n mod m) < 10^9+7 you can simply use the code proposed by #kfx.
We want to compute nCk (mod p). I'll handle when 0 <= k <= p-2, because Lucas's theorem handles the rest.
Wilson's theorem states that for prime p, (p-1)! = -1 (mod p), or equivalently (p-2)! = 1 (mod p) (by division).
By division: (k!)^(-1) = (p-2)!/(k!) = (p-2)(p-3)...(k+1) (mod p)
Thus, the binomial coefficient is n!/(k!(n-k)!) = n(n-1)...(n-k+1)/(k!) = n(n-1)...(n-k+1)(p-2)(p-3)...(k+1) (mod p)
Voila. You don't have to do any inverse computations or anything like that. It's also fairly easy to code. A couple optimizations to consider: (1) you can replace (p-2)(p-3)... with (-2)(-3)...; (2) nCk is symmetric in the sense that nCk = nC(n-k) so choose the half that requires you to do less computations.

Finding binomial coefficient for large n and k modulo m

I want to compute nCk mod m with following constraints:
n<=10^18
k<=10^5
m=10^9+7
I have read this article:
Calculating Binomial Coefficient (nCk) for large n & k
But here value of m is 1009. Hence using Lucas theorem, we need only to calculate 1009*1009 different values of aCb where a,b<=1009
How to do it with above constraints.
I cannot make a array of O(m*k) space complexity with given constraints.
Help!
The binominal coefficient of (n, k) is calculated by the formula:
(n, k) = n! / k! / (n - k)!
To make this work for large numbers n and k modulo m observe that:
Factorial of a number modulo m can be calculated step-by-step, in
each step taking the result % m. However, this will be far too slow with n up to 10^18. So there are faster methods where the complexity is bounded by the modulo, and you can use some of those.
The division (a / b) mod m is equal to (a * b^-1) mod m, where b^-1 is the inverse of b modulo m (that is, (b * b^-1 = 1) mod m).
This means that:
(n, k) mod m = (n! * (k!)^-1 * ((n - k)!)^-1) mod m
The inverse of a number can be efficiently found using the Extended Euclidean algorithm. Assuming you have the factorial calculation sorted out, the rest of the algorithm is straightforward, just watch out for integer overflows on multiplication. Here's reference code that works up to n=10^9. To handle for larger numbers the factorial computation should be replaced with a more efficient algorithm and the code should be slightly adapted to avoid integer overflows, but the main idea will remain the same:
#define MOD 1000000007
// Extended Euclidean algorithm
int xGCD(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
int x1, y1, gcd = xGCD(b, a % b, x1, y1);
x = y1;
y = x1 - (long long)(a / b) * y1;
return gcd;
}
// factorial of n modulo MOD
int modfact(int n) {
int result = 1;
while (n > 1) {
result = (long long)result * n % MOD;
n -= 1;
}
return result;
}
// multiply a and b modulo MOD
int modmult(int a, int b) {
return (long long)a * b % MOD;
}
// inverse of a modulo MOD
int inverse(int a) {
int x, y;
xGCD(a, MOD, x, y);
return x;
}
// binomial coefficient nCk modulo MOD
int bc(int n, int k)
{
return modmult(modmult(modfact(n), inverse(modfact(k))), inverse(modfact(n - k)));
}
Just use the fact that
(n, k) = n! / k! / (n - k)! = n*(n-1)*...*(n-k+1)/[k*(k-1)*...*1]
so you actually have just 2*k=2*10^5 factors. For the inverse of a number you can use suggestion of kfx since your m is prime.
First, you don't need to pre-compute and store all the possible aCb values! they can be computed per case.
Second, for the special case when (k < m) and (n < m^2), the Lucas theorem easily reduces to the following result:
(n choose k) mod m = ((n mod m) choose k) mod m
then since (n mod m) < 10^9+7 you can simply use the code proposed by #kfx.
We want to compute nCk (mod p). I'll handle when 0 <= k <= p-2, because Lucas's theorem handles the rest.
Wilson's theorem states that for prime p, (p-1)! = -1 (mod p), or equivalently (p-2)! = 1 (mod p) (by division).
By division: (k!)^(-1) = (p-2)!/(k!) = (p-2)(p-3)...(k+1) (mod p)
Thus, the binomial coefficient is n!/(k!(n-k)!) = n(n-1)...(n-k+1)/(k!) = n(n-1)...(n-k+1)(p-2)(p-3)...(k+1) (mod p)
Voila. You don't have to do any inverse computations or anything like that. It's also fairly easy to code. A couple optimizations to consider: (1) you can replace (p-2)(p-3)... with (-2)(-3)...; (2) nCk is symmetric in the sense that nCk = nC(n-k) so choose the half that requires you to do less computations.

How to use a very long integer to compute a value in C++?

I need to compute (n*(2n+1)*(n+1)*(3(n^2)+3n+1))/30 modulo m where:
- 30 & m can be non co-prime
- n can have values up to 10^10 (too big for long long int)
- m can have any value up to 10000
I have tried this:
long long int tp1;
double k;
k=n;
k=k*((2*n)+1);
k=k*(n+1);
k=k*((3*n*n)+(3*n)-1);
tp1=fmod(k/30,m);
As noted by molbdnilo, you can do all the calculations modulo a certain number.
To expand that idea:
(x * y) mod m is the same as ((x mod m) * (y mod m)) mod m
(x + y) mod m is the same as ((x mod m) + (y mod m)) mod m
However
(x / y) mod m is not the same as ((x mod m) / (y mod m)) mod m
Therefore, you have to calculate n*(2n+1)*(n+1)*(3(n^2)+3n+1) mod (30 * m), and divide that by 30.
P.S. I assumed the division operation means the same as in c++, "divide with rounding down".
For very long integer, use GMP from the Gnu project.
GMP
With the c++ variant (gmpxx), you have just to déclare your number like this :
mpz_class number;
And you can effectuate your calculs like this :
number = k*((3*n*n)+(3*n)-1);
where k and n can be int or mpz_class (or many others).
I hope that will help you !