看這個以前建議先看一下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 }