E. Card Game
In the most popular card game in Berland, a deck of $n \times m$ cards is used. Each card has two parameters: suit and rank. Suits in the game are numbered from $1$ to $n$, and ranks are numbered from $1$ to $m$. There is exactly one card in the deck for each combination of suit and rank.
A card with suit $a$ and rank $b$ can beat a card with suit $c$ and rank $d$ in one of two cases:
- $a = 1$, $c \ne 1$ (a card of suit $1$ can beat a card of any other suit);
- $a = c$, $b > d$ (a card can beat any other card of the same suit but of a lower rank).
Two players play the game. Before the game starts, they receive exactly half of the deck each. The first player wins if for every card of the second player, he can choose his card that can beat it, and there is no card that is chosen twice (i. e. there exists a matching of the first player's cards with the second player's cards such that in each pair the first player's card beats the second player's card). Otherwise, the second player wins.
Your task is to calculate the number of ways to distribute the cards so that the first player wins. Two ways are considered different if there exists a card such that in one way it belongs to the first player and in the other way it belongs to the second player. The number of ways can be very large, so print it modulo $998244353$.
Input
The only line contains two integers $n$ and $m$ ($1 \le n, m \le 500$).
Additional constraint on the input: $m$ is even.
Output
Print a single integer — the number of ways to distribute the cards so that the first player wins, taken modulo $998244353$.
Examples
Input
1 4
Output
2
Input
2 2
Output
2
Input
3 6
Output
1690
Input
5 4
Output
568
Input
500 500
Output
84693741
解题思路
参考的官方题解,已经写的很详细了。
首先因为第 $1$ 种花色可以与任意一种花色匹配,而其余的花色只能同类型匹配。因此玩家一拥有的第 $1$ 种花色牌不少于玩家二,且玩家一拥有的其他花色牌不多于玩家二。
我们先考虑只有第 $1$ 种花色的匹配方案数。从等级高到低依次分牌。如果将当前牌分给玩家一,那么将其存到待匹配的候选区中。否则将当前牌分给玩家二,我们需要从候选区中选出一张与其匹配,如果候选区中没牌就无法匹配,则这不是一个合法的匹配方案。可以发现这个过程和括号匹配十分相似,把分给玩家一的牌看作是 (
,分给玩家二的牌看作是 )
,合法的匹配就要求任意一个前缀 (
的不少于 )
。但由于玩家一拥有的第 $1$ 种花色牌可以多于玩家二,因此 $m$ 次匹配后并不要求 (
的数量恰好等于 )
的数量。
因此问题变成了求括号匹配方案数,这个可以用简单 dp 进行求解。定义 $g(i,j)$ 表示匹配了前 $i$ 个位置,且每个前缀的 (
不少于 )
,完成第 $i$ 次匹配后 (
比 )
的数量多 $j$ 的方案数。根据第 $i$ 个位置是 (
或 )
进行状态划分,转移方程就是$$g(i,j) = g(i-1,j-1) + g(i-1,j+1)$$
当分完第 $1$ 种花色的牌后,不妨假设玩家一比玩家二多出了 $j$ 张,接下来依次分剩余花色的牌(因为其余花色只能同类型匹配,因此每种花色的分配都是独立的)。这 $j$ 张多出的牌可以与任意剩余花色的任意一张牌匹配,假设第 $i \, (i \geq 2)$ 种花色中有 $k$ 张是与第 $1$ 种花色匹配的,意味着玩家一比玩家二少 $k$ 张第 $i$ 种花色的牌。此时我们要考虑有多少种方案使得第 $i$ 种花色的牌互相匹配后,还剩 $k$ 张分给玩家二用于与第 $1$ 种牌匹配。
同样可以转换成括号匹配的问题,不过此时由于玩家二的牌不少于玩家一,我们定义分给玩家一的牌看作是 )
,分给玩家二的牌看作是 (
,并且从等级低到高依次分牌。剩下的分析过程和上面的类似,最后合法的匹配方案数就是 $g(m,k)$。
现在我们要把这 $j$ 张都分给剩余的花色进行匹配,要求这样的方案数还是通过 dp。定义 $f(i,j)$ 表示处理完前 $i$ 种花色的牌后玩家一还多出 $j$ 张第 $1$ 种花色的牌的方案数。根据玩家一用多少张第 $1$ 种花色的牌与玩家二的第 $i$ 种牌匹配进行状态划分,转移方程就是
$$
\begin{cases}
f(i,j) = g(m,j) &,i = 1 \\
f(i,j) = \sum\limits_{k=0}^{m-j}{f(i-1,j+k) \times g(m,k)} &,i \geq 2
\end{cases}
$$
最后答案就是 $f(n,0)$。
AC 代码如下,时间复杂度为 $O\left(n m^2\right)$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 505, mod = 998244353;
int f[N][N], g[N][N];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
g[0][0] = 1;
for (int i = 1; i <= m; i++) {
for (int j = 0; j <= i; j++) {
g[i][j] = g[i - 1][j + 1] % mod;
if (j) g[i][j] = (g[i][j] + g[i - 1][j - 1]) % mod;
}
}
memcpy(f[1], g[m], m + 1 << 2);
for (int i = 2; i <= n; i++) {
for (int j = 0; j <= m; j++) {
for (int k = 0; j + k <= m; k++) {
f[i][j] = (f[i][j] + 1ll * f[i - 1][j + k] * g[m][k]) % mod;
}
}
}
cout << f[n][0];
return 0;
}
参考资料
Educational Codeforces Round 170 Editorial:https://codeforces.com/blog/entry/135173
标签:花色,匹配,玩家,player,Game,Card,suit,card From: https://www.cnblogs.com/onlyblues/p/18470598