[组合数]求组合数的几种方法总结
求C(n,m)%mod的方法總結
1.當n,m都非常小的時候能夠利用楊輝三角直接求。
C(n,m)=C(n-1,m)+C(n-1,m-1)。
2.利用乘法逆元。
乘法逆元:(a/b)%mod=a*(b^(mod-2)) mod為素數。
逆元能夠利用擴展歐幾里德或歐拉函數求得:
1. n!/(m!*(n-m)! =x%p ,先對算出n!、m!
、(n-m)!對p取模的余數。就轉換為a/b=x%p;由于p為素數。所以等價于bx+py=a;然后用擴展的歐幾里得定理算出 bx’+py’=1的解。x=x’*a,就得到了終于的x的值,即C(m,n)%p得值。
2.逆元 事實上假設mod是素數 則b的逆元事實上就是b^(mod-2)
也就是 (m!(n-m)!)的逆元為 (m!(n-m)!)p-2 ;
1 : (long long)(MOD - MOD / a) * inv(MOD % a) % MOD; } LL C(LL n,LL m) { if(m < 0)return 0; if(n < m)return 0; if(m > n-m) m = n-m; LL up = 1, down = 1; for(LL i = 0 ; i < m ; i ++){ up = up * (n-i) % MOD; down = down * (i+1) % MOD; } return up * inv(down) % MOD; }
3.當n和m比較大,mod是素數且比較小的時候(10^5左右)。通過Lucas定理計算
Lucas定理:A、B是非負整數,p是質數。A B寫成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]) mod p同余
即:Lucas(n,m,p)=C(n%p,m%p)*Lucas(n/p,m/p,p)
C(n % mod, m % mod) % mod; 假設太大還是利用上面的逆元來處理。
半預處理
由于Lucas定理保證了階乘的數均小于p,所以能夠講全部的階乘先預處理,優化C(n,m)
mod的要求:p<10^6,且為素數
有效范圍:1<=n,m<=10^9
4.另一種就是分解質因子。這個比較麻煩。
http://www.mamicode.com/info-detail-621758.html
總結
以上是生活随笔為你收集整理的[组合数]求组合数的几种方法总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 移动医疗未来还有多少红利?
- 下一篇: 【Java框架】 Hibernate与M