组合数取模与卢卡斯定理

inv[i] = ( MOD - MOD / i ) * inv[MOD%i] % MOD
证明:
设t = MOD / i , k = MOD % i
则有 t * i + k == 0 % MOD
有 -t * i == k % MOD
两边同时除以ik得到:-t * inv[k] == inv[i] % MOD
即 inv[i] == -MOD / i * inv[MOD%i]
即 inv[i] == ( MOD - MOD / i) * inv[MOD%i]
(适用于MOD是质数的情况,能够O(n)时间求出1~n对模MOD的逆)
(转自:http://blog.csdn.net/iamzky/article/details/21246493)

A、B是非负整数,p是质数。AB写成p进制:A=a[n]a[n-1]…a[0],B=b[n]b[n-1]…b[0]。
则组合数C(A,B)与C(a[n],b[n])C(a[n-1],b[n-1])…*C(a[0],b[0]) modp同余
即:Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p)
eg:以求解n! % p为例,把n分段,每p个一段,每一段求的结果是一样的。但是需要单独处理每一段的末尾p, 2p, …,把p提取出来,会发现剩下的数正好又是(n / p)!,相当于划归成了一个子问题,这样递归求解即可。
这个是单独处理n!的情况,当然C(n,m)就是n!/(m!*(n-m)!),每一个阶乘都用上面的方法处理的话,就是Lucas定理了,注意这儿的p是素数是有必要的。
Lucas最大的数据处理能力是p在10^5左右
(转自:http://blog.csdn.net/pi9nc/article/details/9615359)

常见取值情况:
(1)1 m n 1000和1 p 109

 这个问题比较简单,组合数的计算可以靠杨辉三角,那么由于和的范围小,直接两层循环即可。

(2)1 m n 1018 和2 p 105 ,并且是素数
这个问题有个叫做Lucas的定理,定理描述是,如果:
n= nkpk + nk1pk1 + nk2pk2 +…+ n1p + n0
m= mkpk + mk1pk1 + mk2pk2 +…+ m1p + m0
那么得到 Cmn = ki=0 Cmini (mod p)
这样然后分别求,采用逆元计算即可。(根据费马小定理:(m!(n-m)!)的逆元为 (m!(nm)!)p2
(3)1 m n 106 和1 p 105 ,并且可能为合数
这样的话先采取暴力分解,然后快速幂即可。
(转自:http://blog.csdn.net/acdreamers/article/details/8037918)

你可能感兴趣的:(组合数取模,卢卡斯定理)