0365 巨大组合数
* * * *
拉格朗日计划
* * * *
巨大组合数

$\binom{10^{18}}{10^9}$有超过90亿位数。

记$M(n,k,m)$为$\binom{n}{k}$模m的余数。

求$\sum_{p,q,r}M(10^{18},10^9,pqr)$,其中$p < q < r$取遍1000到5000之间的全部素数。

本题难度:



解答

本题的思路很直接,先生成素数列表。对每个素数p,用Lucas定理计算出$\binom{n}{k}$模p的余数,再用中国剩余定理将其组合起来即可,最终结果是$162619462356610313$。

import itertools

target=5000
d=[0]*target
n=2
while n < target:
    for i in range(n*n,target,n):
        d[i]=d[i]+1
    n=n+1
    while n < target and d[n]>0:
        n=n+1

primeList=[k for k in range(1000,target) if d[k]==0]
a={}
f=[0]*(target+1)
inverses={}

C=lambda n,k,p:0 if k>n else ((f[n]*inverses[p][f[k]])%p)*(inverses[p][f[n-k]]%p)
lucas=lambda n,k,p:1 if n==0 else (C(n%p,k%p,p)*lucas(n/p,k/p,p))%p
CRT=lambda a,b,c,p,q,r:(a*inverses[p][(q*r)%p]*q*r+b*inverses[q][(p*r)%q]*p*r+c*inverses[r][(p*q)%r]*p*q)%(p*q*r)

for p in primeList:
    inverses[p]=[0]*p
    inverses[p][1]=1
    for i in range(2,p):
        inverses[p][i]=((p-p/i)*inverses[p][p%i])%p
    f[0]=1
    for i in range(1,p):
        f[i]=(f[i-1]*i)%p
    a[p]=lucas(10**18,10**9,p)

print sum(CRT(a[p],a[q],a[r],p,q,r) for p,q,r in itertools.combinations(primeList,3) if a[p] or a[q] or a[r])