#include <cstdio>
typedef long long ll;
ll frac[100005]; //frac[i]表示i!
void ext_gcd(int a,int b,int &x,int &y)
{
if( !b )
{
x = 1;
y = 0;
}else
{
ext_gcd(b,a%b,y,x);
y -= a / b * x;
}
}
int inv(int t,int p) //求t关于p的逆元
{
int x,y;
ext_gcd(t,p,x,y);
x = ( x % p + p ) % p;
return x;
}
int lucas(int n,int m,int p) //计算c(n,m)%p
{
if( n < m ) return 0;
if( n >= p || m >= p ) //卢卡斯定理
return ( lucas(n/p,m/p,p) * lucas(n%p,m%p,p) ) % p;
//直接组合数公式计算出结果
int res;
int t = ( frac[n-m] * frac[m] ) % p;
t = inv(t,p); //求分母逆元
res = ( frac[n] * t ) % p;
return res;
}
int main()
{
int t;
scanf("%d",&t);
while( t-- )
{
int n,m,p;
scanf("%d%d%d",&n,&m,&p);
frac[0] = 1;
for (int i = 1; i <= n+m; i++)
{
frac[i] = frac[i-1] * i;
frac[i] %= p;
}
printf("%d\n",lucas(n+m,m,p));
}
return 0;
}
卢卡斯定理
最新推荐文章于 2023-07-03 09:14:45 发布