-
组合数学
-
公式
(二项式定理)
-
O(n)预处理,O(1)求组合数预处理阶乘fac数组。
预处理fac数组,需取模,则需处理出ifac(阶乘逆元)。
code:
fac[0]=1;
for(int i=1;i<N;i++) fac[i]=fac[i-1]*i%p;
ifac[N-1]=power(fac[N-1],mod-2);
for(int i=N-2;~i;i--) ifac[i]=ifac[i+1]*i+1;
然后用套公式即可。
-
Lucas定理
核心:
Lucas定理用于求一些n,m很大,但是p比较小的组合数直接记公式即可。
code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int N=1e5+10;
int T;
LL fac[N];
LL n,m,p;
LL qpow(LL a,LL b)
{
LL res=1;
a%=p;
while(b)
{
if(b&1)res=a*res%p;
a=a*a%p;b>>=1;
}return res%p;
}
LL C(LL n,LL m)
{
if(n<m)return 0;
return fac[n]%p*qpow(fac[m],p-2)%p*qpow(fac[n-m],p-2)%p;
}
LL Lucas(LL n,LL m)
{
if(m==0)return 1;
return Lucas(n/p,m/p)%p*C(n%p,m%p)%p;
}
int main()
{
scanf("%d",&T);
fac[0]=1;
while(T--)
{
scanf("%lld%lld%lld",&n,&m,&p);
for(int i=1;i<=p;i++)fac[i]=(fac[i-1]*i)%p;
printf("%lld
",Lucas(n+m,m));
}
}