太喜欢这个题了,这个题出得很启发性,我以前还没见过,于是把这个题记录下来。

题面

在伯兰最流行的纸牌游戏中,使用的是一副 \(n \times m\) 纸牌。每张牌都有两个参数:花色和等级。游戏中花色的编号从 \(1\) 到 \(n\),等级的编号从 \(1\) 到 \(m\)。每种花色和等级的组合都有一张牌。

  • \(a = 1\), \(c \ne 1\) (花色为 \(1\) 的牌可以战胜其他花色的牌);
  • \(a = c\), \(b > d\) (一张牌可以击败同花色但等级较低的任何其他牌).

两名玩家进行游戏。游戏开始前,他们每人正好得到一半的牌。如果第一位玩家可以为第二位玩家的每一张牌选择一张可以击败它的牌,并且没有被选择两次的牌(即第一位玩家的牌与第二位玩家的牌存在配对,在每一对牌中,第一位玩家的牌击败第二位玩家的牌),则第一位玩家获胜。否则,第二名玩家获胜。

你的任务是计算有多少种分配牌的方法能让第一名玩家获胜。如果有一张牌在一种分配方式中属于第一名玩家,而在另一种分配方式中属于第二名玩家,那么这两种分配方式就被认为是不同的。方法的数量可能非常大,输出答案对 \(998244353\) 的模。

唯一一行包含两个整数 \(n\) 和 \(m\) (\(1 \le n, m \le 500\)) 为偶数。

输入的其他限制条件:\(m\) 为偶数。

题解

这个题乍一看很 \(dp\) 但是实际上这个题可以用组合数学推出答案。

对同样花色的牌,考虑什么情况下才能获胜,显然是对于所有的先手 (\(A\)) 的牌都可以找到一个后手 (\(B\)) 的牌使得 \(A\) 的牌面比 \(B\) 大,考虑括号匹配。

对于任意一个前缀 \(A\) 选择第 \(i\) 张牌则第 \(i\) 位置为左括号,否则被 \(B\) 选择就是右括号,对于任意前缀,必定满足左括号数不小于右括号数,考虑状态转移。

记 \(dp[i][j]\) 表示考虑的前 \(i\) 个位置,其中有 \(j\) 个左括号赘余(没有被右括号匹配),则对于下一个位置要么增加一个左括号,要么减少一个左括号,状态转移如下:

\[dp[i + 1][j] = dp[i][j - 1] + dp[i][j + 1]
\]

我们选择第一行的牌(花色为 \(1\))的时候的所有情况被 \(dp\) 数组所包含,接下来考虑剩下第 \(2 \sim n\) 行的牌,此部分 \(A\) 必不可能多选,否则必定存在一张牌不能在同行匹配,会被 \(B\) 用一张 \(1\) 匹配,所以此时右括号赘余,考虑前面所有 \(A\) 的牌会被抵消掉,仅仅把多余的牌替换为 \(B\) 的牌即可,也就是说这一部分的贡献和第一行完全一样,考虑对第 \(2 \sim n\) 行的方案数卷积,即:

\[f[k] = \sum_{x + y = k}g[x] \times h[y]
\]

这个转移是直觉的,因为对两行分别赘余 \(x\), \(y\) 张牌,总共赘余的牌有 \(x + y\) 张,而由于所有的行是相同的,做 \(n - 1\) 次卷积:

\[\forall k \le m, f[i][k] = \sum_{x + y = k} f[i - 1][x] * dp[m][y]
\]

最后我们的答案需要第一行赘余的左括号与其余行赘余的右括号完全匹配,可以列出:

\[answer = \sum_{i = 0}^{m}dp[m][i] * f[n - 1][i]
\]

参考代码(滚动数组优化)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 510;
const ll mod = 998244353;
int n, m; int main()
{
cin >> n >> m;
vector<ll> dp(m + 1), f(m + 1);
dp[0] = f[0] = 1;
for (int i = 0; i < m; i ++ )
{
vector<ll> tmp(m + 1);
for (int j = 0; j <= i; j ++ )
{
(tmp[j + 1] += dp[j]) %= mod;
if (j) (tmp[j - 1] += dp[j]) %= mod;
}
swap(tmp, dp);
}
for (int i = 1; i < n; i ++ )
{
vector<ll> tmp(m + 1);
for (int x = 0; x <= m; x ++ )
for (int y = 0; x + y <= m; y ++ )
(tmp[x + y] += f[x] * dp[y] % mod) %= mod;
swap(tmp, f);
}
ll ans = 0;
for (int i = 0; i <= m; i ++ ) (ans += dp[i] * f[i] % mod) %= mod;
cout << ans;
return 0;
}

CF2025E Card Game 题解的更多相关文章

  1. Clash Credenz 2014 Wild Card Round题解

    A题 简单模拟. /************************************************************************* > File Name: ...

  2. CF1492B Card Deck 题解

    Content 有 \(n\) 张纸牌组成的一个牌堆,每张纸牌都有一个价值 \(p_1,p_2,\dots,p_n\).每次选出最顶上的几个牌放到另外一个一开始为空的牌堆里面.定义一个牌堆的总值为 \ ...

  3. CF106A Card Game 题解

    Content 一种纸牌游戏有许多张卡牌,每张卡牌有一个套装(S,H,D和 C)和一个等级(按升序排列6,7,8,9,T, J,Q,K,A). 规定以下情况卡牌 A 才能赢卡牌 B: A 有王牌套装, ...

  4. MinMax 容斥 学习笔记

    基本形式 \[ \max(S) = \sum_{T\subseteq S, T \neq \varnothing} (-1)^{|T|-1}\min(T) \] 证明 不提供数学证明. 简要讲一下抽象 ...

  5. 【题解】P3129高低卡(白金)High Card Low Card

    [题解][P3129 USACO15DEC]高低卡(白金)High Card Low Card (Platinum) 考虑贪心. 枚举在第几局改变规则,在改变规则之前,尽量出比它大的最小的牌,在改变规 ...

  6. HDU 4336 Card Collector(状压 + 概率DP 期望)题解

    题意:每包干脆面可能开出卡或者什么都没有,一共n种卡,每种卡每包爆率pi,问收齐n种卡的期望 思路:期望求解公式为:$E(x) = \sum_{i=1}^{k}pi * xi + (1 - \sum_ ...

  7. 【题解】HDU4336 Card Collector

    显然,这题有一种很简单的做法即直接状压卡牌的状态并转移期望的次数.但我们现在有一个更加强大的工具——min-max容斥. min-max 容斥(对期望也成立):\(E[max(S)] = \sum_{ ...

  8. [OpenJudge 3061]Flip The Card

    [OpenJudge 3061]Flip The Card 试题描述 There are N× Ncards, which form an N× Nmatrix. The cards can be p ...

  9. cdoj 31 饭卡(card) 01背包

    饭卡(card) Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/31 Des ...

  10. 《ACM国际大学生程序设计竞赛题解Ⅰ》——基础编程题

    这个专栏开始介绍一些<ACM国际大学生程序设计竞赛题解>上的竞赛题目,读者可以配合zju/poj/uva的在线测评系统提交代码(今天zoj貌似崩了). 其实看书名也能看出来这本书的思路,就 ...

随机推荐

  1. 使用VSCode搭建UniApp + TS + Vue3 + Vite项目

    uniapp是一个使用Vue.js开发所有前端应用的框架,开发者编写一套代码,可发布到iOS.Android.以及各种小程序.深受广大前端开发者的喜爱.uniapp官方也提供了自己的IDE工具HBui ...

  2. SQL Server – 执行计划和各种 join 方式 (Execution plan & Join Pattern)

    前言 我几乎从来没有遇到过性能问题, 毕竟项目真的太小了. 一般上只要用常识去建 index 就可以了. 但是这并不阻碍我对知识的追求. 这篇是关于一些性能优化和原理的内容. 纯属学习, 希望未来有机 ...

  3. JavaScript – Symbol

    前言 Symbol 是 es6 的特性. 如果只是写业务逻辑代码, 其实是不太会用到的. 如果是做架构, 封装, UI 组件才有需要. 但学它的概念是好的. es6 有需要内置的 Symbol 链接者 ...

  4. 前端基本功——面试必问系列(1):都2024了,还没吃透Promise?一文搞懂

    写在前面: 大家好,我是山里看瓜,该系列文章是为了帮助大家不管面试还是开发对前端的一些基本但是很重要的知识点认识更加深入和全面. 想写这个系列文章的初衷是:我发现前端的很多基本知识,使用起来很简单,定 ...

  5. Powershell 重新排列 Windows环境变量

    最近乱搞环境变量,然后有些重复了,遂写个脚本去重下排序下. 环境变量有长度限制,如果超出了,比如SqlServer相关的,将共同路径单独搞个变量声明下,比如 将其路径手动替换成如下,可大幅压缩变量长度 ...

  6. linux 映射windows 下的共享文件夹

    linux 映射windows 下的共享文件夹     本文讯]2021年4月27日  在对接第三方系统,进行数据采集的时候,对方给了我们一个文件夹,里面全是txt文件,这个时候就要想办法获取他们数据 ...

  7. 系统编程-进程-先后fork或open一个文件的区别

    关联博文: 当文件操作遇上fork Linux内核的文件结构体 struct file { ......... struct path f_path; //文件的路径 #define f_dentry ...

  8. 优化 Go 语言数据打包:性能基准测试与分析

    优化 Go 语言数据打包:性能基准测试与分析 场景:在局域网内,需要将多个机器网卡上抓到的数据包同步到一个机器上. 原有方案:tcpdump -w 写入文件,然后定时调用 rsync 进行同步. 改造 ...

  9. 伯克利函数调用排行榜(BFCL)

    自 2022 年底以来,大语言模型(LLMs)凭借其执行通用任务的强大能力,成为众人关注的焦点.不仅限于聊天应用,将这些模型应用于开发各类 AI 应用和软件(如 Langchain, Llama In ...

  10. 《TensorFlow+Keras自然语言处理实战》已出版

    <TensorFlow+Keras自然语言处理实战>已出版 当当京东天猫均有出售.清华社官网信息如下: http://www.tup.tsinghua.edu.cn/booksCenter ...