模板更新 扩展卢卡斯
写个模板。扩展卢卡斯。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+10; ll fac[N],PI[N],PK[N],cnt; ll qmod(ll a,ll b,ll p) { ll ans=1; while(b) { if(b&1)ans=ans*a%p; a=a*a%p;b>>=1; } return ans; } void exgcd(ll a,ll b,ll &x,ll &y) { if(!b){x=1;y=0;return;} exgcd(b,a%b,y,x);y-=a/b*x; } ll inv(ll n,ll p) { ll a=n,b=p,x,y; exgcd(a,b,x,y); x=(x%b+b)%b; if(!x)x+=b; return x; } ll mul(ll n,ll pi,ll pk) { if(!n)return 1; ll ans=1; if(n/pk) { ans=ans*fac[pk]%pk; ans=qmod(ans,n/pk,pk)%pk; } ans=ans*fac[n%pk]%pk; return ans*mul(n/pi,pi,pk)%pk; } ll C(ll n,ll m,ll p,ll pi,ll pk) { if(n<m)return 0;int k=0;ll ans=1; fac[0]=fac[1]=1; for(int i=2;i<=pk;++i) { if(i%pi)fac[i]=fac[i-1]*i%pk; else fac[i]=fac[i-1]; } ll a=mul(n,pi,pk),b=mul(m,pi,pk),c=mul(n-m,pi,pk); 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; ans=a*inv(b,pk)%pk*inv(c,pk)%pk*qmod(pi,k,pk)%pk; return ans*(p/pk)%p*inv(p/pk,pk)%p; } ll CRT(ll n,int m,int p) { if(n<m)return 0;ll ans=0; for(int i=1;i<=cnt;++i) { ans=(ans+C(n,m,p,PI[i],PK[i]))%p; } return ans; } void pri(int p) { cnt=0; for(int i=2;i*i<=p;++i) { if(p%i==0) { PI[++cnt]=i;PK[cnt]=1; while(p%i==0)p/=i,PK[cnt]*=i; } } if(p!=1)PI[++cnt]=PK[cnt]=p; return; } int main() { int T;scanf("%d",&T);ll n,m,p; while(T--) { scanf("%lld%lld%lld",&n,&m,&p);pri(p);//n+=m; printf("%lld\n",CRT(n,m,p)); } return 0; }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。