之前有寫過一篇部落格是求組合數(取模)的兩種方法。那篇文章裡介紹的方法其實也還有侷限性,pascal打表由於記憶體的限制一般只用於求取1000以內的組合數,而使用逆元套公式的方法其實也只適用於求取的組合數 c(
n,m)
%p中,n 和 m均不大於要求的模數 p 。這樣就導致了乙個很尷尬的問題——如果要求取的組合數超過了模數p,這個時候有要怎麼辦呢。本人之前由於水平限制並沒有了解到這個問題,前幾天打玲瓏杯#round 4的時候被這個問題困擾了,經隊友提醒才知道有lucas定理這種東西。這裡就另寫一篇文章,其實是作為之前的「組合數取模的兩種方法」的乙個拓展篇。將這個問題一次性終結到底。
盧卡斯(lucas)定理設 p這裡還要宣告一點,本篇部落格的參考書籍為馮志剛版《初等數論》第37頁,下面給出原書的證明:為素數,a,
b∈n∗
,並且 a=
akpk
+ak−
1pk−
1+⋯+
a1p+
a0b=
bkpk
+bk−
1pk−
1+⋯+
b1p+
b0這裡 0
≤ai,
bi≤p
−1都是整數, i
=0,1
,2,⋯
,k. 則有 c
ba≡c
bkak
∗cbk
−1ak
−1∗⋯
∗cb0
a0(m
odp)

這個定理的意義就在於把
a 或者
b或者兩者均大於
p 的組合數 cb
a轉換為求解小於
p 的整數 ak
和 bk 的組合數 cb
kak 的乘積。
而對於 a0
,a1,
⋯,ak
可以通過秦九韶演算法: a=
(((⋯
(0∗p
+ak)
⋯)∗p
+a2)
∗p+a
1)∗p
+a0
逆向得到,即 a0
=(a/
p0)%
pa1=
(a/p
1)%p
a2=(
a/p2
)%p⋮
ak=(
a/pk
)%p
顯然,秦九韶的逆向演算法頁同樣適用於求解
b .
實際求解 cb
a時,只要 ai
和 bi 當中有乙個仍然大於
p ,就要繼續使用逆向的秦九韶演算法。但實際編寫**的過程,只需要遞迴即可:
其中c(a, b)的函式在之前的文章求組合數(取模)的兩種方法敘述過了,這裡就不繼續贅述了。ll lucas(ll a, ll b)
現在,通過pascal打表的方法在 o(
1)的時間裡求得小範圍的組合數,用逆元的方法可以求取模數範圍內的組合數,在加上lucas定理,就可以求取任意範圍內的組合數了。
在實際運用的過程中,可以根據實際判斷哪種方法最適合,a,
b 的是乙個主導因素,同事,演算法的簡單性也是乙個主導因素。畢竟,越簡單的東西越不容易出錯。殺雞用牛刀不是不可以,但是你想過雞的感受麼。。。
以上です~
盧卡斯(Lucas)定理
c nm modp cn pm p cnm odpm modp modp c n m mod p c times c mod p cnm mo dp c n pm p cnmo dpmm odp modp p為素數 int qpow ll b,int n,int mod return res int...
盧卡斯定理Lucas
在數論中,lucas 定理用於快速計算 c m n p 即證明 c m n prod kc 其中 m i 為 m 的因式分解,n i 為 n 的因式分解,p 為質數。由 edward lucas 在1878年提出。證明 首先我們將 c i p 進行一下變式即 c i j frac 提出來乙個 fra...
盧卡斯定理 Lucas
當 p 為質數,1 le m le n 時,求組合數 c bmod 對於質數 p,有 begin c equiv c cdot c pmod end 其中 n p 和 m p 為整除。引理1 begin c equiv frac cdot c equiv 0 pmod end 引理1證明 begin...