题解:CF2025E Card Game

首先发现第 \(2\) 到 \(n\) 花色的卡牌都是等价的,不受他们花色的影响,能决定其分配方案数的是第一名玩家有多少张多余的 \(1\) 花色卡牌来换掉 \(2\) 到 \(n\) 花色的卡牌。

因此,我们可以先预处理出在得到在确定给某种花色分配 \(x\) 张 \(1\) 花色卡牌时该花色的分配方案数,记为 \(p_x\)。由于 \(2\) 到 \(n\) 不同花色的牌不能互相打,而 \(m\) 又是偶数,所以分配 \(1\) 花色卡牌数必须是偶数。考虑如何算出这个数组,除去被降维打击的牌,剩下的牌按等级从小到大排序,由于第一位玩家必须打败第二位的所有牌,我们可以视为一个长度为 \(m-x\) 的数组 \(a\),如果第 \(i\) 张牌给第一位玩家就是令 \(a_i = -1\),否则 \(a_i = 1\),求 \(a\) 的前缀和数组任意一位均大于等于 \(0\) 的方案数。这是简单的,设 \(t_{i,j}\) 表示已决定 \(a\) 的前 \(i\) 位,有 \(j\) 位为 \(-1\) 的方案数,显然有转移

\[t_{i,0}=t_{i-1,0},t_{i,j} = t_{i-1,j-1} + t_{i-1,j} (1 \le i \le m,1 \le j \le 2 \times i) \]

显然 \(p_x\) 即为 \(t_{m,\frac{m-x}{2}}\)。

接下来考虑假如已经确定了第一位玩家一共有 \(y\) 张多余的 \(1\) 花色牌,把这些牌分配给 \(2\) 到 \(n\) 花色的方案数。设 \(f_{i,j}\) 表示已完成对 \(2\) 到 \(i\) 花色的分配,已经用了 \(j\) 张 \(1\) 花色的方案数,设在第 \(i\) 个花色分配了 \(2 \times k\) 张 \(1\) 花色牌,则有转移

\[f_{i,j} = \sum_{k=0}^{\frac{j}{2}}{f_{i - 1,j - 2 \times k} \times p_{2 \times k}} \]

最后计算答案,枚举 \(y\),由于分配第 \(1\) 类花色的牌使得有 \(y\) 张多余的方案数就是 \(p_y\),不需要再进行计算,直接乘上即可,最终答案为

\[\sum_{i=0}^{\frac{m}{2}}{f_{n,2 \times i} \times pre_{2 \times i}} \]

#include<bits/stdc++.h>
#define MAXN 505
#define int long long
const int inf=1e18,mod=998244353;
using namespace std;
int n,m,p[MAXN],f[MAXN][MAXN],t[MAXN][MAXN],ans;
signed main(){
//	freopen("card.in","r",stdin);
//	freopen("card.out","w",stdout);
	scanf("%lld%lld",&n,&m);
	t[0][0]=1;
	for(int i=1;i<=m;i++){
		for(int j=0;j*2<=i;j++){
			t[i][j]=t[i-1][j];
			if(j>0)t[i][j]=(t[i][j]+t[i-1][j-1])%mod;
		}
	}
	for(int i=0;i<=m;i+=2){
		p[i]=t[m][(m-i)/2];
	}
	f[1][0]=1;
	for(int i=2;i<=n;i++){
		for(int j=0;j<=m;j+=2){
			for(int k=0;k<=j;k+=2){
				f[i][j]=(f[i][j]+f[i-1][j-k]*p[k]%mod)%mod;
			}
		}
	}
	for(int i=0;i<=m;i+=2){
		int sum=p[i]*f[n][i]%mod;
		ans=(ans+sum)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2025-11-02 00:19  CharlieCai2024  阅读(28)  评论(0)    收藏  举报