解决带模数的组合数问题--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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值