使用模乘法逆的概念来计算nCr%MOD

时间:2014-03-13 20:39:07

标签: c++ conceptual

我为n

的大值计算nCr%MOD

我使用关系式(n + 1)Cr =(nCr)*(n + 1)/(n + 1-r)

我必须迭代一个循环,以获得不同的n值,保持r不变。

llu fact=1;
/*The loop begins from i>=M+1 */
fact=(fact*(i-1)*modInverse(i-M,MOD))%MOD;  // Single statement executed during each iteration of loop


  Here I'm calculating (i-1)C(M-1)
  Here M and MOD are constant values 
  MOD=1000000009 and llu refers to unsigned long long

我正在做的是

(n+1)Cr % MOD = [ (nCr) * (n+1) * modInverse(n+1-r) ] % MOD

这里modInverse根据以下定义计算模乘法逆:

llu modPow(llu a, llu x, llu p)
{
    //calculates a^x mod p
    llu res = 1;
    while(x > 0)
    {
        if( x % 2 != 0)
        {
            res = (res * a) % p;
        }
        a = (a * a) % p;
        x /= 2;
    }
    return (res%MOD);
}
llu modInverse(llu a, llu p)
{
    //calculates the modular multiplicative of a mod m assuming p is prime
    return modPow(a, p-2, p);
}

现在问题是我没有为n的大值(10 ^ 6)得到正确的nCr值。是我的方法

(n+1)Cr % MOD = [ (nCr) * (n+1) * modInverse(n+1-r) ] % MOD

概念上错了?

1 个答案:

答案 0 :(得分:0)

是的,底部的公式在数学上是合理的。

然而,通过在取模数之前进行2次乘法,这会增加溢出问题的可能性。

例如,MOD是O(10 ^ 10),因此modInverse也是O(10 ^ 10)。如果n是O(10 ^ 6),则乘积是O(10 ^ 26),这是O(2 ^ 86)并且会导致uint64溢出,并给出错误的答案。请考虑一下:

(n+1)Cr % MOD = [ ([(nCr) * (n+1)] % MOD) * modInverse(n+1-r) ] % MOD

您可能也对我对this suspiciously similar question的回答感兴趣。