题目连接: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;
}