如何在不调用溢出的情况下在C或C ++中计算机(N choose K)%M?
对于 N(4 <= N <= 1000)且 K(1 <= K <= N)且 M = 1000003的特定情况
答案 0 :(得分:13)
要计算(n选择k)%M,您可以分别计算分母(n!)模数M和分母(k!*(n - k)!)模数M,然后将分母乘以分母的模数乘法逆(M中)。由于M是素数,你可以使用费马的小定理来计算乘法逆。
在以下链接上有一个很好的解释,带有示例代码(问题SuperSum):
答案 1 :(得分:3)
由于1000000003 = 23 * 307 * 141623,你可以计算(n选择k)mod 23,307和141623,然后应用中文提醒定理[1]。在计算n!,k时!和(n-k)!,你应该计算每个步骤的每个模式23,307和141623,以防止溢出。
这样即使在32位机器上也应避免溢出。
稍微改进就是计算(n选择k)mod 141623和7061(23 * 307)(编辑:但计算反模数7061可能有点棘手,所以我不会这样做)< / p>
对不起我的英语很差。
[1] http://en.wikipedia.org/wiki/Chinese_remainder_theorem
Edit2:我发现的另一个潜在问题是计算n时! mod 23(例如)它可能是0,但这并不意味着(n choses k)是0 mod 23,所以你应该计算23除以n!,(n-k)的次数!和k!在计算之前(n选择k)。计算这很容易,p除以n!确切的楼层(n / p)+楼层(n /p²)+ ...次。如果它发生了23分n!同样它划分k!和(n-k)!,你继续计算(n选择k)mod 23每次乘以它的23乘以它。这同样适用于307,但不适用于141623
答案 2 :(得分:2)
您可以使用您提供的链接中的递归公式,并执行计算模型M.
答案 3 :(得分:1)
这是一个简单的例子:
(A * B * C) % N ... is equal to... ((A % N) * (B % N) * (C % N)) % N;
也就是说,您需要将模数应用于每个操作数和产品,或者只要它变为大数字。最后,模数必须适用于整体结果。
答案 4 :(得分:-1)
使用Stirling's approximation计算二项式系数。然后像往常一样计算模量。