HDU 6397 Character Encoding(容斥+费马组合数)

 题意:给T组数,n,m,k从0~n-1中选m个数之和为k个方法数对998244353取模输出

题解:

  1.      对于x1+x2+x3+....+xm=k(xi>=0)有C(k+m-1,m-1)个解
  2. a是不能被质数p整除的正整数     a^(p-1)≡1(modp)     -->   a^(p-2)=1/a(modp)  则a^p-2为a的逆元

对于x1,x2,x3,....xm,若符合条件  xi<n--->xi'=xi

                                不符合条件 xi>n---->xi'=xi-n 

   则x1+x2+.....+xm=k-c*n在有c个不符合情况的条件下有C(k-c*n+m-1,m-1)个解

  容斥原理枚举不符合条件的个数

 容斥求和:C(n,0)-C(n,1)+C(n,2)-C(n,3)+C(n,4)-......+(-1)^m*C(n,m)

#include <stdio.h>
#include <iostream>
using namespace std;
const int MOD=998244353;
const int MAXN=202020;
int fac[MAXN],facinv[MAXN];

long long quickmul(int a,int b)
{
	long long ret=1;
	for(; b ; b >>=1 ,a =(long long) a * a % MOD)
		if((b & 1))
			ret=ret * a % MOD;
	return ret;
}
long long C(int n,int m)
{
	if(n<0||m<0||n<m)
		return 0;
	return (long long)fac[n]*facinv[m]%MOD*facinv[n-m]%MOD;
} 
void init()
{
	fac[0]=1;
	for(int i=1;i<=MAXN;i++)
		fac[i]=(long long)fac[i-1]*i%MOD;
	facinv[MAXN]=quickmul(fac[MAXN],MOD-2);
	for(int i=MAXN;i>0;i--)
		facinv[i-1]=(long long)facinv[i]*(i)%MOD;
		//1/(i-1)!=i/(i)!
}
void solve()
{
	int n,m,k;
	scanf("%d %d %d",&n,&m,&k);
	int ans=0;
	for(int c=0;c*n<=k;c++)
	{
		if((c&1))
		{
			ans=(ans - C(m,c) * C(k - c*n + m-1, m-1) % MOD + MOD ) % MOD;
		}else
		{
			ans=(ans + C(m,c) * C(k - c*n + m-1, m-1) % MOD ) % MOD; 
		}
	}
	printf("%d\n",ans);
}
int main()
{
	int T;
	scanf("%d",&T);
	init();
	while(T--)
	{
		solve();
	}	
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_41603898/article/details/81737363
今日推荐