I need to calculate nCr mod p efficiently. Right now, I have written this piece of code, but it exceeds the time limit. Please suggest a more optimal solution.
For my case, p = 10^9 + 7 and 1 ≤ n ≤ 100000000
I have to also make sure that there is no overflow as nCr mod p is guaranteed to fit in 32 bit integer, however n! may exceed the limit.
def nCr(n,k):
r = min(n-k,k)
k = max(n-k,k)
res = 1
mod = 10**9 + 7
for i in range(k+1,n+1):
res = res * i
if res > mod:
res = res % mod
res = res % mod
for i in range(1,r+1):
res = res/i
return res
PS : Also I think my code may not be completely correct. However, it seems to work for small n correctly. If its wrong, please point it out !
A naive approach is to calculate nCr using formulae by applying modular operations at any time. Hence time complexity will be O(q*n). A better approach is to use fermat little theorem.
@toothie It comes from the formula: C(n, r) = n (n - 1) ... (n - r + i) ... (n - r + 1) / 1.2. ... .i. ... r can be re-written as C(n, r) = (n / r) ((n - 1) / (r - 1)) ...
From http://apps.topcoder.com/wiki/display/tc/SRM+467 :
long modPow(long a, long x, long p) {
//calculates a^x mod p in logarithmic time.
long res = 1;
while(x > 0) {
if( x % 2 != 0) {
res = (res * a) % p;
}
a = (a * a) % p;
x /= 2;
}
return res;
}
long modInverse(long a, long p) {
//calculates the modular multiplicative of a mod m.
//(assuming p is prime).
return modPow(a, p-2, p);
}
long modBinomial(long n, long k, long p) {
// calculates C(n,k) mod p (assuming p is prime).
long numerator = 1; // n * (n-1) * ... * (n-k+1)
for (int i=0; i<k; i++) {
numerator = (numerator * (n-i) ) % p;
}
long denominator = 1; // k!
for (int i=1; i<=k; i++) {
denominator = (denominator * i) % p;
}
// numerator / denominator mod p.
return ( numerator* modInverse(denominator,p) ) % p;
}
Notice that we use modpow(a, p-2, p) to compute the mod inverse. This is in accordance to Fermat's Little Theorem which states that (a^(p-1) is congruent to 1 modulo p) where p is prime. It thus implies that (a^(p-2) is congruent to a^(-1) modulo p).
C++ to Python conversion should be easy :)
About the last question: I think that the mistake in your code is to compute the product, reduce it modulo k, and then divide the result by r!. This is not the same as dividing before reducing modulo k. For example, 3*4 / 2 (mod 10) != 3*4 (mod 10) / 2.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With