5

现在 CodeSprint 3 结束了,我一直想知道如何解决这个问题。对于较大的 r 和 n (0<=n<=10^9 ; 0<=r<=n),我们需要简单地计算 nCr mod 142857。我使用了一种递归方法,它通过 min(r, nr) 迭代来计算组合。事实证明这还不够有效。我尝试了几种不同的方法,但它们似乎都不够有效。有什么建议么?

4

1 回答 1

9

For non-prime mod, factor it (142857 = 3^3 * 11 * 13 * 37) and compute C(n,k) mod p^q for each prime factor of the mod using the general Lucas theorem, and combine them using Chinese remainder theorem.

For example, C(234, 44) mod 142857 = 6084, then

  • C(234, 44) mod 3^3 = 9
  • C(234, 44) mod 11 = 1
  • C(234, 44) mod 13 = 0
  • C(234, 44) mod 37 = 16

The Chinese Remainder theorem involves finding x such that

  • x = 9 mod 3^3
  • x = 1 mod 11
  • x = 0 mod 13
  • x = 16 mod 37

The result is x = 6084.

Example

C(234, 44) mod 3^3

First convert n, k, and n-k to base p

n = 234_10 = 22200_3

k = 44_10 = 1122_3

r = n-k = 190_10 = 21001_3

Next find the number of carries

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

Now create the factorial function needed for general Lucas

def f(n, p):
    r = 1
    for i in range(1, n+1):
        if i % p != 0:
            r *= i
    return r

Since q = 3, you will consider only three digits of the base p representation at a time

So

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

Now

s = 1 if p = 2 and q >= 3 else -1

Then

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

Now you have

-60474102975 / 7 mod 3^3

This is a linear congruence and can be solved with

ModularInverse(7, 3^3) = 4
4 * -60474102975 mod 27 = 9

Hence C(234, 44) mod 3^3 = 9

于 2012-11-03T17:52:14.493 回答