现在CodeSprint 3已经结束,我一直想知道如何解决这个问题。我们需要简单地针对r和n的大值计算nCr mod 142857(0 <= n <= 10 ^ 9; 0 <= r <= n)。我使用递归方法,通过min(r,n-r)迭代来计算组合。结果证明这不够有效。我尝试过几种不同的方法,但它们似乎都不够高效。有什么建议吗?
答案 0 :(得分:8)
对于非素数mod,使用一般Lucas定理对因子(142857 = 3 ^ 3 * 11 * 13 * 37)进行因子并计算模型的每个素因子的C(n,k)mod p ^ q,并且用中国剩余定理将它们组合起来。
例如,C(234,44)mod 142857 = 6084,然后
中国剩余定理涉及找到x这样
结果是x = 6084。
C(234,44)mod 3 ^ 3
首先将n,k和n-k转换为基础p
n = 234_10 = 22200_3
k = 44_10 = 1122_3
r = n-k = 190_10 = 21001_3
接下来找到承载次数
e[i] = number of carries from i to end
e 4 3 2 1 0
1 1
r 2 1 0 0 1
k 1 1 2 2
n 2 2 2 0 0
现在创建一般卢卡斯所需的阶乘函数
def f(n, p):
r = 1
for i in range(1, n+1):
if i % p != 0:
r *= i
return r
由于q = 3,您将一次仅考虑基本p表示的三位数
所以
f(222_3, 3)/[f(210_3, 3) * f(011_3, 3)] *
f(220_3, 3)/[f(100_3, 3) * f(112_3, 3)] *
f(200_3, 3)/[f(001_3, 3) * f(122_3, 3)] = 6719344775 / 7
现在
s = 1 if p = 2 and q >= 3 else -1
然后
p^e[0] * s * 6719344775 / 7 mod 3^3
e[0] = 2
p^e[0] = 3^2 = 9
s = -1
p^e[0] * s * 6719344775 = -60474102975
现在你有了
-60474102975 / 7 mod 3^3
这是线性同余,可以用
解决ModularInverse(7, 3^3) = 4
4 * -60474102975 mod 27 = 9
因此,C(234,44)mod 3 ^ 3 = 9