解决带模数的组合数问题--lucas定理

lucas定理公式:

C_{n}^{m} % p = C_{n/p}^{m/p} * C_{n%p}^{m%p} % p

 我是推不来的,放个公式就溜XD

然后求组合数的时候因为要取模,直接阶乘会gg,所以还要用下逆元,还是不会!

果然数论题还是背板子吧QwQ

code:

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <ctime>
#define maxn 200000
#define LL long long
using namespace std;

int t,n,m,mo;
LL fac[maxn];

int read()
{
	int xx=0,kk=1;char ch=' ';
	while(!isdigit(ch)){ch=getchar();if(ch=='-')kk=-1;}
	while(isdigit(ch)){xx=xx*10+ch-'0';ch=getchar();}
	return kk*xx;
}

LL poww(LL a,LL b)
{
	LL ans=1ll,base=a;
	while(b)
	{
		if(b&1) ans=(ans*base)%mo;
		base=(base*base)%mo;
		b>>=1;
	}
	return ans;
}

LL C(LL n,LL m)
{
	if(m>n) return 0;
	return (fac[n]*poww(fac[m],mo-2)%mo)*poww(fac[n-m],mo-2)%mo;
}

LL lucas(LL n,LL m)
{
	if(!m) return 1ll;
	return C(n%mo,m%mo)*lucas(n/mo,m/mo)%mo;
}

int main()
{
	t=read();fac[0]=1;
	while(t--)
	{
		n=read(),m=read(),mo=read();
		for(int i=1;i<=mo;++i) fac[i]=fac[i-1]*i%mo;
		printf("%lld\n",lucas(n+m,n));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40942982/article/details/82787294