标签:href font www. ati blank ble algo code std
其实这个算法挺简单的。
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; }
标签:href font www. ati blank ble algo code std
原文地址:https://www.cnblogs.com/sky-zxz/p/9674167.html