lucas定理
介绍
lucas定理用于解决模数p较小的组合数问题
其主要定理有:
lucas(n,m,p)=combin(n%p,m%p)*lucas(n/p.m/p,p)
边界条件为当n<p时return combin(n,m,p)
combin(n,m,p)=n!*(m!*(n-m))^p-2;
题意:
链接:
https://www.luogu.org/problemnew/show/P3807
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,c,d,e,a[500000],b[500000];
ll qsm(ll x,ll y)
{
if (y==1) return(x);
if (y%2==0)
{
return((ll)(pow(qsm(x,y/2),2))%e);
} else
{
return(((ll)(pow(qsm(x,y/2),2))%e*x)%e);
}
}
ll combin(ll x,ll y)
{
if (y>x) return(0);
return ((a[x]*b[y]) %e*b[x-y])%e;
}
ll lucas(ll x,ll y)
{
if (x>=e) return (combin(x%e,y%e)*lucas(x/e,y/e))%e;
else return combin(x,y);
}
int main()
{
freopen("noip.in","r",stdin);
freopen("noip.out","w",stdout);
cin>>n;
for (ll i=1;i<=n;i++)
{
cin>>c>>d>>e; a[0]=b[0]=1; c+=d;
for (ll j=1;j<=e;j++)
{
a[j]=(a[j-1]*j)%e;
b[j]=qsm(a[j],e-2);
}
cout<<lucas(c,d)<<endl;
}
}