CF1716F Bags with Balls

该文章详细解释了一道数学编程题,涉及在每个包含m个编号球的n个袋子里选择一个球,计算所有可能方案中奇数编号球数量的k次方之和。利用第二类斯特林数和组合数学的知识,通过动态规划方法求解此问题,最终时间复杂度为O(k^2+tk)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CF1716F Bags with Balls

题目大意

n n n个袋子,每个袋子里面有 m m m个球,分别标号为 1 , 2 , … , m 1,2,\dots,m 1,2,,m

你需要在每个袋子中取一个球,然后计算出你取出的标号是奇数的球的数量,记这个数量为 F F F,求所有可能的取球方案的 F k F^k Fk的和对 998244353 998244353 998244353取模后的值。

t t t组数据。

1 ≤ t ≤ 5000 , 1 ≤ n , m ≤ 998244352 , 1 ≤ k ≤ 2000 1\leq t\leq 5000,1\leq n,m\leq 998244352,1\leq k\leq 2000 1t5000,1n,m998244352,1k2000


题解

x x x表示 m m m个球中编号为奇数的球的个数, y y y表示 m m m个球中编号为偶数的球的个数。那么 x = ⌈ m 2 ⌉ x=\lceil\dfrac m2\rceil x=2m y = ⌊ m 2 ⌋ y=\lfloor\dfrac m2\rfloor y=2m
我们来推一下式子。枚举 F F F值,题意即求

∑ i = 0 n i k × C n i × x i y n − i \qquad\sum\limits_{i=0}^ni^k\times C_n^i\times x^iy^{n-i} i=0nik×Cni×xiyni

由第二类斯特林数可得 n m = ∑ i = 0 m S ( m , k ) × C n k × k ! n^m=\sum\limits_{i=0}^mS(m,k)\times C_n^k\times k! nm=i=0mS(m,k)×Cnk×k!,所以原式可变为

∑ i = 0 n C n i × x i y n − i × ∑ j = 0 k S ( k , j ) × C i j × j ! \qquad\sum\limits_{i=0}^nC_n^i\times x^iy^{n-i}\times \sum\limits_{j=0}^kS(k,j)\times C_i^j\times j! i=0nCni×xiyni×j=0kS(k,j)×Cij×j!

= ∑ j = 0 k S ( k , j ) ∑ i = 0 n n ! i ! ( n − i ) ! × i ! ( i − j ) ! × x i y n − i \quad =\sum\limits_{j=0}^kS(k,j)\sum\limits_{i=0}^n\dfrac{n!}{i!(n-i)!}\times \dfrac{i!}{(i-j)!}\times x^iy^{n-i} =j=0kS(k,j)i=0ni!(ni)!n!×(ij)!i!×xiyni

将组合数拆开可得

∑ j = 0 k S ( k , j ) ∑ i = 0 n n ! ( n − i ) ! ( i − j ) ! x i y n − i \qquad \sum\limits_{j=0}^kS(k,j)\sum\limits_{i=0}^n\dfrac{n!}{(n-i)!(i-j)!}x^iy^{n-i} j=0kS(k,j)i=0n(ni)!(ij)!n!xiyni

= ∑ j = 0 k S ( k , j ) n ! ( n − j ) ! ∑ i = 0 n C n − j n − i x i y n − i \quad =\sum\limits_{j=0}^kS(k,j)\dfrac{n!}{(n-j)!}\sum\limits_{i=0}^nC_{n-j}^{n-i}x^iy^{n-i} =j=0kS(k,j)(nj)!n!i=0nCnjnixiyni

枚举 n − i n-i ni可得

∑ j = 0 k S ( k , j ) n ! ( n − j ) ! ∑ i = 0 n − j C n − j i x n − i y i \qquad\sum\limits_{j=0}^kS(k,j)\dfrac{n!}{(n-j)!}\sum\limits_{i=0}^{n-j}C_{n-j}^ix^{n-i}y^i j=0kS(k,j)(nj)!n!i=0njCnjixniyi

= ∑ j = 0 k S ( k , j ) n ! ( n − j ) ! ∑ i = 0 n − j C n − j i x j ⋅ x n − i − j y j \quad =\sum\limits_{j=0}^kS(k,j)\dfrac{n!}{(n-j)!}\sum\limits_{i=0}^{n-j}C_{n-j}^{i}x^j\cdot x^{n-i-j}y^j =j=0kS(k,j)(nj)!n!i=0njCnjixjxnijyj

= ∑ j = 0 k S ( k , j ) n ! ( n − j ) ! x j ( x + y ) n − j \quad =\sum\limits_{j=0}^kS(k,j)\dfrac{n!}{(n-j)!}x^j(x+y)^{n-j} =j=0kS(k,j)(nj)!n!xj(x+y)nj

= ∑ j = 0 k S ( k , j ) n ! ( n − j ) ! x j m n − j \quad =\sum\limits_{j=0}^kS(k,j)\dfrac{n!}{(n-j)!}x^jm^{n-j} =j=0kS(k,j)(nj)!n!xjmnj

求出这个式子即可。

时间复杂度为 O ( k 2 + t k ) O(k^2+tk) O(k2+tk)

code

#include<bits/stdc++.h>
using namespace std;
const int N=2000;
int T;
long long ans,ny,s[2005][2005];
long long mod=998244353;
long long mi(long long t,long long v){
	if(!v) return 1;
	long long re=mi(t,v/2);
	re=re*re%mod;
	if(v&1) re=re*t%mod;
	return re;
}
void init(){
	s[1][1]=1;
	for(int i=2;i<=N;i++){
		for(int j=1;j<=i;j++){
			s[i][j]=(s[i-1][j-1]+j*s[i-1][j]%mod)%mod;
		}
	}
}
int main()
{
	init();
	long long n,m,k;
	scanf("%d",&T);
	while(T--){
		scanf("%lld%lld%lld",&n,&m,&k);
		ans=0;
		long long v=(m+1)/2;
		ny=mi(m,mod-2);
		long long tmp=n*v%mod*mi(m,n-1)%mod;
		for(int i=1;i<=min(n,k);i++){
			ans=(ans+s[k][i]*tmp%mod)%mod;
			tmp=tmp*(n-i)%mod*ny%mod*v%mod;
		}
		printf("%lld\n",ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值