题目连接:http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=628
|
那么可以这样考虑:C(n,m)= n!/(m!*(n-m)!) 将分子和分母分别转化为素因子乘积的形式,然后上下同时约去,最后用快速幂搞一下就行了
如果p为素数的话,那么可以用lucas定理搞~
#include <iostream> #include <stdio.h> #include <string> #include <string.h> #include <algorithm> const int N=1e5+100; using namespace std; typedef long long ll; int n,m,p,ct; ll prime[2*N]; bool isprime[2*N]; int t[5][2*N]; void solve() { ct=0; memset(isprime,false,sizeof(isprime)); isprime[0]=isprime[1]=true; for(int i=2;i<=200100;i++) { if(!isprime[i]) { prime[++ct]=i; for(int j=i+i;j<=200100;j+=i) isprime[j]=true; } } } int cal(int x,int pos) { int i=1; for(;i<=ct&&prime[i]<=x;i++) { int ans=0,tmp=prime[i]; while(x/tmp!=0) { ans+=x/tmp; tmp*=prime[i]; } t[pos][i]=ans; } return i; } ll quick(ll a,int b ) { ll ans=1; while(b) { if(b&1)ans=ans*a%p; b=b/2; a=a*a%p; } return ans; } int main() { int T; scanf("%d",&T); solve(); while(T--) { scanf("%d%d%d",&n,&m,&p); memset(t,0,sizeof(t)); if(n-1==0) { printf("1\n"); continue; } if(n-1==1) { printf("%d\n",(n+m-2)%p); continue; } int t1=cal(n+m-2,1); int t2=cal(n-1,2); int t3=cal(m-1,3); int cnt=max(t1,max(t2,t3)); for(int i=1;i<cnt;i++) { t[1][i]=t[1][i]-t[2][i]-t[3][i]; } ll ans=1; for(int i=1;i<cnt;i++) { ans=ans*quick(prime[i],t[1][i])%p; } printf("%lld\n",ans); } return 0; }
原文:http://blog.csdn.net/liusuangeng/article/details/44026067