盧卡斯定理及其擴充套件 模板
阿新 • • 發佈:2021-07-13
\(……\)貌似沒甚麼要說明的
\(Lucas\)定理
#include<bits/stdc++.h> using namespace std; typedef long long ll; int t,g; int qpow(int a,int b,int md){ ll res=1; for(;b;b>>=1,a=(ll)a*a%md) if(b&1) res=(ll)res*a%md; return res; } ll C(int x,int y,int p){ if(y>x) return 0; if(y>x-y) y=x-y; ll a=1,b=1; for(int i=0;i<y;i++){ a=(a*(x-i))%p; b=(b*(i+1))%p; } return a*qpow(b,p-2,p)%p; } ll Lucas(int x,int y,int p){ if(y==0) return 1; return Lucas(x/p,y/p,p)*C(x%p,y%p,p)%p; } int main(){ cin>>t; for(int k=1;k<=t;k++){ int n,m; cin>>n>>m>>g; cout<<Lucas(n+m,m,g)<<endl; } }
注:這也是\(P3807\)的正解
擴充套件\(Lucas\)定理
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll n,m,p; ll exgcd(ll a,ll b,ll &x,ll &y){ if(!b){ x=1,y=0; return a; } ll d=exgcd(b,a%b,y,x); y-=(a/b)*x; return d; } ll qpow(ll a,ll b,ll md){ int res=1; for(;b;b>>=1,a=(ll)a*a%md) if(b&1) res=(ll)res*a%md; return res; } ll fac(ll n,ll pi,ll pk){ if(!n) return 1; ll res=1; for(ll i=2;i<=pk;++i) if(i%pi) (res*=i)%=pk; res=qpow(res,n/pk,pk); for(ll i=2;i<=n%pk;++i) if(i%pi) (res*=i)%=pk; return res*fac(n/pi,pi,pk)%pk; } ll inv(ll n,ll mod){ ll x,y; exgcd(n,mod,x,y); return (x+=mod)>mod?x-mod:x; } ll CRT(ll b,ll mod){ return b*inv(p/mod,mod)%p*(p/mod)%p; } ll C(ll n,ll m,ll pi,ll pk){ ll up=fac(n,pi,pk),d1=fac(m,pi,pk),d2=fac(n-m,pi,pk); ll k=0; for(ll i=n;i;i/=pi) k+=i/pi; for(ll i=m;i;i/=pi) k-=i/pi; for(ll i=n-m;i;i/=pi) k-=i/pi; return up*inv(d1,pk)%pk*inv(d2,pk)%pk*qpow(pi,k,pk)%pk; } ll exLucas(ll n,ll m){ ll res=0,tmp=p,pk; int lim=sqrt(p)+5; for(ll i=2;i<=lim;++i) if(tmp%i==0){ pk=1; while(tmp%i==0) pk*=i,tmp/=i; (res+=CRT(C(n,m,i,pk),pk))%=p; } if(tmp>1) (res+=CRT(C(n,m,tmp,tmp),tmp))%=p; return res; } int main(){ cin>>n>>m>>p; cout<<exLucas(n,m); return 0; }
注:這也是\(P4720\)的正解