Lucas定理是用於處理組合數取模的定理,當m,n較大時使用
它可以將一個大組合數取模,轉化成很多小組合數相乘取模(n<p, m<p)
模板:
LL Lucas(LL n,LL m,LL p)
{
if(!m) return 1;
return C(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;
}
代碼:
求後面的小組合數,可以將下面公式中分子的逆元求出來,轉化爲乘積
#include <iostream>
#include<stdio.h>
#include<cmath>
#include<algorithm>
#define mod 1000000007
#include<string.h>
using namespace std;
typedef long long LL;
const int manx=1e5+7;
LL a[manx];
LL quick_pow(LL a,LL b,LL m)
{
LL ans=1;
while(b)
{
if(b&1)
ans=(ans*a)%m;
a=(a*a)%m;
b>>=1;
}
return ans;
}
LL C(LL n,LL m,LL p)
{
if(m>n)return 0;
return ((a[n]*quick_pow(a[m],p-2,p))%p*quick_pow(a[n-m],p-2,p)%p);
}
LL Lucas(LL n,LL m,LL p)
{
if(!m) return 1;
return C(n%p,m%p,p)*Lucas(n/p,m/p,p)%p;
}
int main()
{
LL n,m,p,t;
scanf("%lld",&t);
a[0]=1;
while(t--)
{
scanf("%lld%lld%lld",&n,&m,&p);
for(int i=1;i<=p;i++)a[i]=(a[i-1]*i)%p;
printf("%lld\n",Lucas(n+m,m,p));
}
}