主要繞過費馬小定理來證明lucas定理,挺有意思..此外設定多進製計算機可以通過移位運算直接加快多進製運算的速度。
1.lucas定理
lucas定理解決的問題是組合數取模。數學上來說,就是求 (n
m)modp
。這裡n,m
可能很大,比如達到
1015,而p
在109以內。顯然運用常規的階乘方法無法直接求解,所以引入lucas定理。把n和
m寫成p進製數的樣子(如果長度不一樣把短的補成長的那個的長度):n=
(a0a
1…ak
)pm=
(b0b
1…bk
)p那麼:(nm
)≡∏k
i=0(
aibi
)modp證明
如果把lucas定理從遞迴的角度理解,它其實是這樣的:設n=
ap+b
,m=c
p+d,
(b,d
a=⌊n
p⌋,c
=⌊mp
⌋)(n
m)≡(
ac)∗
(bd)
這個定理的乙個很巧妙的證法是通過二項式定理來說明上面的式子是成立的。
首先,對於任意質數pp,有:(1
+x)p
≡1+x
pmod
p其證明可以由費馬小定理(xp
≡xmodp)|
p為素數
)直接得出:(1
+x)p
≡1+x
xp≡x
所以(1+
x)p≡
1+x≡
1+xp
(當然同樣也有(a+
b)p≡
ap+b
pmod
p,具體為什麼你可以拆開前面的式子,將其除 ap
和 bp 項外的所有項的係數好好研究一下(其實就是楊輝三角的第p層),可以發現把對稱項係數分別合併後都能整除p)
利用這個性質,我們證明lucas定理:(1
+x)n
=(1+
x)⌊n
p⌋∗p
(1+x
)b=(
1+xp
)⌊np
⌋(1+
x)b=
∑i=0
k(⌊n
p⌋i)
xpi∑
j=0k
(bj)
xj考察等式左右兩邊xmxm的係數,可以發現:左邊
右邊=(
nm)=
(⌊np
⌋i)(
bj),
(pi+
j=m,
j=(⌊n
p⌋⌊m
p⌋)(
bd)所以上面的式子成立,證明完畢。
如果不算預處理什麼的,演算法時間複雜度為o(l
ogpn
)。如果能夠支援預處理,那麼就加乙個o(
p),要不就用快速冪,乘上o(
logp
)。2. 線性求所有逆元的方法
前幾天在看 lucas 定理的時候發現要求 1,
2,⋯,
p−1mod
p 的逆元,然後就看到了乙個 θ(
n)的做法發現太神了,雖然想起來是挺簡單的
這個做法實際上是這樣的,首先 1−1
≡1(modp)
然後我們設 p=k
⋅i+r
,r1<
i<
p再將這個式子放到
modp
意義下就會得到k⋅
i+r≡
0(modp
)兩邊同時乘上 i−1
⋅r−1
就會得到k⋅
r−1+
i−1i
−1i−
1≡≡≡
0−k⋅
r−1−
⌊pi⌋
⋅(pmodi)
−1(modp)
(modp)
(modp)
於是就可以從前面推出當前的逆元了,**也就一行
a[i] = -(p / i) * a[p % i];
related posts:
[數論]miller-rabin素性測試
[數論]二次剩餘及計算方法
擴充套件歐幾里得演算法與中國剩餘定理
bzoj-3157. 國王奇遇記
bzoj-3771. triple
盧卡斯 Lucas 定理 逆元 求組合數
參考文章 lucas定理是用來求 c n,m mod p,p為素數的值。lucas定理 我們令n sp q m tp r.q r p 那麼 在程式設計時你只要繼續對 呼叫lucas定理即可。可以遞迴的去完成這個過程,其中遞迴終點為t 0 時間o logp n p ll lucas ll a,ll b...
乘法逆元 線性求mod p的所有數逆元
逆元存在的 求單個逆元,一般用快速冪或者擴充套件歐幾里得演算法,複雜度為log p 若是遞推求解所有逆元,複雜度為線性。前幾天在看 lucas 定理的時候發現要求 1,2 p 1modp 1,2,p 1modp 的逆元,然後就看到了乙個 n n 的做法發現太神了,雖然想起來是挺簡單的 這個做法實際上...
數論 線性求所有逆元的方法
前幾天在看 lucas 定理的時候發現要求 1,2 p 1modp 1,2,p 1modp 的逆元,然後就看到了乙個 n n 的做法發現太神了,雖然想起來是挺簡單的 這個做法實際上是這樣的,首先 1 1 1 modp 1 1 1 modp 然後我們設 p k i r r1 i p p k i r,r...