1. 程式人生 > >【數論】Lucas定理

【數論】Lucas定理

方法 代碼 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>
#define
ll 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 int
i=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定理