【Coel.學習筆記】盧卡斯定理(Lucas Theorem)
阿新 • • 發佈:2021-12-23
題前碎語
這周要開家長會,回去就要把自選科目選定了。
當然選課對我來說沒什麼(物生地YYDS!),但是選課就意味著要分班,就要和原本實驗班的同學說再見了……
\(qwq\)……
筆記內容
本筆記含有盧卡斯定理。
盧卡斯定理
盧卡斯定理(\(Lucas\) \(Theorem\),又名\(Lucas\)定理)是一種用於求解大組合數取模的定理,能夠在\(O(klogn)\)的時間複雜度下求解大組合數取模,但必須保證取模數為質數。
盧卡斯定理的基本形式為:
即把\(n\)與\(m\)分解為\(p\)進位制數,對該進位制每一位求解組合數並相加。
因此,這也要求\(p\)
在實際實現中可以寫成遞迴的形式,遞迴邊界即為\(C^0_n=1\)。
程式碼如下:洛谷傳送門
#include<cstdio> #include<cctype> #define maxn 100050 long long n,m,p,T; long long read() { long long x=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-')f=-1; ch=getchar(); } while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar(); } return x*f; } long long qpow(long long a,long long b,long long p) { long long sum=1; while(b) { if(b&1)sum=sum*a%p; a=a*a%p; b>>=1; } return sum; } long long C(long long n,long long m,long long p) { if(m>n)return 0; long long a=1,b=1; for(int i=n-m+1;i<=n;i++) a=a*i%p; for(int i=2;i<=m;i++) b=b*i%p; return a*qpow(b,p-2,p)%p;//考慮到p必定是質數,所以用費馬小定理求逆元 } long long Lucas_Theorem(long long n,long long m,long long p) { return m?(C(n%p,m%p,p)*Lucas_Theorem(n/p,m/p,p))%p:1; } int main() { T=read(); while(T--) { n=read(),m=read(),p=read(); printf("%lld\n",Lucas_Theorem(n+m,m,p)); } return 0; }
題後閒話
沒什麼想說的(
學完盧卡斯定理之後再加一個擴充套件尤拉定理就能召喚神龍(bushi)做數論全家桶古代豬文了!
繼續努力……