看这个以前建议先看一下n!……html
对于组合数咱们能够将其表示成阶乘的形式:C(n,k)= 。那咱们不妨把这三个阶乘所有表示成上个专题的形式。这样的话,若是对于e1>e2+e3就能够被p整除,e1=e2+e3就没法被p整除。在没法被整除的状况下C(n,k)=a1(a2a3)-1ide
1 int mod_comb (int n, int k, int p){ 2 if (n<0||k<0||n<k) return 0; 3 int a1=mod_fact(n,p,e1),a2=mod_fact(k,p,e2),a3=mod_fact(n-k,p,e3); 4 if (e1>e2+e3)return 0; 5 return a1*mod_inverse(a2*a3%p, p) %p; 6 }
另外,咱们也能够用Lucas来求。spa
Lucas定理:咱们令n=sp+q , m=tp+r(q,r ≤p)则有3d
具体证实以下:code
首先咱们先来证实一个简单的算式:(f!=p&&f!=0)htm
C(p , f)%p= p!/(f!(p-f)!)%p由于p是素数,而且分母上的f和(p-f)都要比p要小,也就是说在分母上没有数能够把p约去,因此C(p,f) %p必定等于0。blog
证实完了这个算式,咱们就能够开始证实卢卡斯定理。get
对于(1+x)sp+q≡(1+x)sp×(1+x)q≡((1+x)p)s×(1+x)q≡(根据二项式定理展开,而后在有上面的公式,因此咱们能够获得)(1+xp)s×(1+x)q≡(再根据二项式定理展开)≡ (mod p)io
最终咱们能够获得event
下面咱们来计算一下左右两边xtp+r的系数:
左边=C(sp+q ,tp+r);右边=C(s ,t)×C(q, r)
由于左边=右边,因此咱们最后获得了卢卡斯定理。
有了卢卡斯定理,咱们就有了这样的代码,这个代码真的很好理解
1 int Lucas(int n,int m,int p){ 2 long long ans=1; 3 while(n&&m&&ans){ 4 ans*=comb(n%p,m%p,p)%p;//comb()求组合数 5 n/=p;m/=p; 6 } 7 return ans; 8 }