0.概述
用於解決組合數取模的問題。請先學習中國剩餘定理,有點作用的。
1.分解
現在我們要求 (mn)modp 的結果,p 是個小傢伙,n,m 長的很魁梧。
現在我們找到 p 的質因數分解 p=i∏piti
我們如果能求出 (mn)modpiti
再用中國剩餘定理合成回去即可了!所以下文就只討論對 pk(p∈P) 取模的情況。
2.硬算
用 (mn)=m!(n−m)!n!
我們試着單獨考慮 n!,m!,(n−m)! 中 p 的倍數,就可以求逆元了。用 f(n)=pxnmodpk 來表示,其中 x 是滿足 px∣n 最大的 x 。
我們將 n! 分成兩部分,一部分是 p 的倍數,另一部分不是。即 n!=i=1∏⌊pn⌋(ip)⋅i=1,¬(p∣i)∏ni
後面那一部分大有搞頭。畢竟你要對 pk 取模,做乘法之前也可以先行取模。我們根據“除以 pk 的商”進行分類,就可以看出 i=1,¬(p∣i)∏ni≡⎝⎛i=1,¬(p∣i)∏pki⎠⎞⌊pkn⌋⋅i=pk⌊pkn⌋+1,¬(p∣i)∏ni(modpk)
然後前面那一坨把 p 提出來,得到 i=1∏⌊pn⌋(ip)=p⌊pn⌋i=1∏⌊pn⌋i=⌊pn⌋!⋅p⌊pn⌋
注意到 ⌊pn⌋! 中可能仍然有 p 的因數,於是要遞歸處理。總結一下就是
f(n)≡f(⌊pn⌋)⋅⎝⎛i=1,¬(p∣i)∏pki⎠⎞⌊pkn⌋⋅i=pk⌊pkn⌋+1,¬(p∣i)∏ni(modpk)
複雜度呢?很明顯是遞推式 T(n)=T(⌊pn⌋)+O(pk+logn) 。不妨認爲 logn 是個小於 pk 的值,就有總複雜度 T(n)=O(pklogn)
顯然,最壞的情況是 O(plogn) 的。中國剩餘定理合併的時間是不用考慮的,很小。
把 p 的因數提了出來,p 的指數是幾呢?衆所周知,x∈Z+,px∣nmaxx=i=1∑+∞⌊pin⌋
然後就完了。可以提一下 k=1 的特殊情況,(mn)≡(m/pn/p)(mmodpnmodp)(modp),p∈P
除法是下取整,P 是質數集合。
代碼
不想寫,今天爆零了,Zz 和 Sy 和 Xjh 和 Zxy 等大佬各種 AK 虐全場。
想看他們的博客,還用南無鍊銅佛的博客做引子。
while(true) cout << "我好菜啊啊啊啊!" << endl;