【數論】Lucas定理
阿新 • • 發佈:2018-09-19
方法 代碼 ron -m div 算法 for using ati
其實這個算法挺簡單的。
Lucas定理:C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p
很明顯,這個可以遞歸求解。
傳統的算組合數的方法是需要計算階乘的,當n和m到了一個很大的數字,那麽這種方法的時間復雜度就過不去,而這時Lucas定理就派上了用場。
時間復雜度:O(logp(n)*p)
模板題:鏈接
代碼:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #definell long long int using namespace std; ll t,p; ll ksm(ll a,ll b){ ll tot=1; while(b){ if(b&1){ tot=(tot*a)%p; } a=(a*a)%p; b>>=1; } return tot; } ll c(ll n,ll m){ if(m>n)return 0; ll t1=1,t2=1; for(register inti=n-m+1;i<=n;i++)t1=(t1*i)%p; for(register int i=1;i<=m;i++)t2=(t2*i)%p; return t1*ksm(t2,p-2)%p; } ll lucas(ll n,ll m){ if(!m)return 1; else return (lucas(n/p,m/p)*c(n%p,m%p))%p; } int main(){ scanf("%lld",&t); while(t){ t--; ll n,m; scanf("%lld%lld%lld",&n,&m,&p); printf("%lld\n",lucas(n+m,m)); } return 0; }
【數論】Lucas定理