E. Card Game

E. Card Game

In the most popular card game in Berland, a deck of n×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, c1 (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 (1n,m500).

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(i1,j1)+g(i1,j+1)

  当分完第 1 种花色的牌后,不妨假设玩家一比玩家二多出了 j 张,接下来依次分剩余花色的牌(因为其余花色只能同类型匹配,因此每种花色的分配都是独立的)。这 j 张多出的牌可以与任意剩余花色的任意一张牌匹配,假设第 i(i2) 种花色中有 k 张是与第 1 种花色匹配的,意味着玩家一比玩家二少 k  张第 i 种花色的牌。此时我们要考虑有多少种方案使得第 i 种花色的牌互相匹配后,还剩 k 张分给玩家二用于与第 1 种牌匹配。

  同样可以转换成括号匹配的问题,不过此时由于玩家二的牌不少于玩家一,我们定义分给玩家一的牌看作是 ),分给玩家二的牌看作是 (,并且从等级低到高依次分牌。剩下的分析过程和上面的类似,最后合法的匹配方案数就是 g(m,k)

  现在我们要把这 j 张都分给剩余的花色进行匹配,要求这样的方案数还是通过 dp。定义 f(i,j) 表示处理完前 i 种花色的牌后玩家一还多出 j 张第 1 种花色的牌的方案数。根据玩家一用多少张第 1 种花色的牌与玩家二的第 i 种牌匹配进行状态划分,转移方程就是

{f(i,j)=g(m,j),i=1f(i,j)=k=0mjf(i1,j+k)×g(m,k),i2

  最后答案就是 f(n,0)

  AC 代码如下,时间复杂度为 O(nm2)

#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

posted @   onlyblues  阅读(82)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2022-10-16 Count Subarrays With Fixed Bounds
2022-10-16 Minimize Maximum of Array
2022-10-16 最短路程
Web Analytics
点击右上角即可分享
微信分享提示