洛谷 P5299 - [PKUWC2018]Slay the Spire(组合数学+dp)
hot tea 啊……这种风格及难度的题放在省选 D2T1 左右还是挺喜闻乐见的罢
首先考虑对于固定的 \(m\) 张牌怎样求出最优的打牌策略,假设我们抽到了 \(p\) 张强化牌,攻击力从大到小分别为 \(x_1,x_2,\cdots,x_p\),以及 \(q\) 张攻击牌,攻击力从大到小分别为 \(y_1,y_2,\cdots,y_q\),显然如果 \(q=0\) 那就没得打了,总攻击力显然为 \(0\),否则你手玩几组数据就能发现我们肯定会尽量打强化牌直到没有强化牌或者只能再打 \(1\) 张牌为止,打完了强化牌再打攻击牌,证明就套路地用下 exchange arguments,假设现在我们选择了 \(s(s<p)\) 张强化牌与 \(t(t\ge 2)\) 张攻击牌,那么造成的伤害的最大值显然为 \(W_1=\prod\limits_{i=1}^sx_i\sum\limits_{j=1}^ty_j\),考虑多打一张攻击牌,那么造成的伤害就变为 \(W_2=\prod\limits_{i=1}^{s+1}x_i\sum\limits_{j=1}^{t-1}y_j\),这里做差不太容易,故考虑做商,\(\dfrac{W_2}{W_1}=x_{s+1}\times\dfrac{\sum\limits_{j=1}^ty_j}{\sum\limits_{j=1}^{t+1}y_j}\),由于 \(t\ge 2\) 且 \(y_j\ge y_{j+1}\),故一定有 \(y_{t+1}\le\sum\limits_{j=1}^ty_j\),故 \(\dfrac{\sum\limits_{j=1}^ty_j}{\sum\limits_{j=1}^{t+1}y_j}\le\dfrac{1}{2}\),而题目规定 \(x_i\ge 2\),故 \(\dfrac{W_2}{W_1}\ge 1\),即 \(W_2\ge W_1\),因此我们的策略是最优的。
接下来将这个结论应用于原题,首先将所有强化牌和攻击牌按从大到小顺序排序。考虑将选择的 \(m\) 张牌中强化牌与攻击牌的数量分为两类:强化牌数量 \(<k-1\) 和 \(\ge k-1\)。我们预处理 \(dp1_{i,j}\) 表示在前 \(i\) 张强化牌中选择 \(j\) 张强化牌,并且强化牌 \(i\) 必须被选择,所有选牌方案的强化牌上值的乘积之和,再预处理 \(dp2_{i,j}\) 表示在前 \(i\) 张攻击牌中选 \(j\) 张,所有选牌方案的值之和的和。对于强化牌数量 \(\le k-1\) 的情况,我们枚举以下三个量:选择的强化牌数量 \(c\in[0,k-2]\)、最后一个(这里及下文中的“最后一个”指下标最大)被选择的强化牌编号 \(i\),以及最后一个被打出去的攻击牌的编号 \(j\),剩下 \(m-k\) 张牌显然只能在剩余 \(n-j\) 张攻击牌中选,产生的贡献为 \(dp1_{i,c}\times dp2_{j,k-c}\times\dbinom{n-j}{m-k}\),\(i\) 的那一维显然可以前缀和优化掉,复杂度 \(n^2\)。对于强化牌数量 \(>k-1\) 的情况,我们枚举最后一个被打出去的强化牌的编号 \(i\),以及唯一一个被出去的攻击牌的编号 \(j\),剩余 \(m-k\) 张牌可以在剩余 \(n-i\) 张强化牌和 \(n-j\) 张攻击牌中选,产生的贡献就是 \(dp1_{i,k-1}\times b_j\times\dbinom{2n-i-j}{m-k}\),随便枚举一下算一算即可。
最后就是怎样预处理 \(dp1_{i,j},dp2_{i,j}\) 的问题了,其实非常容易,显然有 \(dp\) 方程 \(dp1_{i,j}=\sum\limits_{k=0}^{i-1}dp1_{k,j-1}\times a_i\),\(dp2_{i,j}=\sum\limits_{k=0}^{i-1}dp2_{k,j-1}+a_i\times\dbinom{i-1}{j-1}\),\(\sum\) 那一维显然可以前缀和优化掉,复杂度平方,于是这题就做完了。
const int MAXN=3000;
const int MOD=998244353;
int n,m,k,a[MAXN+5],b[MAXN+5],c[MAXN*2+5][MAXN*2+5];
bool cmp(int lhs,int rhs){return lhs>rhs;}
int dpa[MAXN+5][MAXN+5],sdpa[MAXN+5][MAXN+5];
int dpb[MAXN+5][MAXN+5],sdpb[MAXN+5][MAXN+5];
void solve(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
sort(a+1,a+n+1,cmp);sort(b+1,b+n+1,cmp);
dpa[0][0]=sdpa[0][0]=1;
for(int i=1;i<=n;i++){
sdpa[i][0]=1;
for(int j=1;j<=i;j++){
dpa[i][j]=1ll*a[i]*sdpa[i-1][j-1]%MOD;
sdpa[i][j]=(sdpa[i-1][j]+dpa[i][j])%MOD;
// printf("%d %d %d\n",i,j,dpa[i][j]);
}
}
for(int i=1;i<=n;i++) for(int j=1;j<=i;j++){
dpb[i][j]=(1ll*b[i]*c[i-1][j-1]%MOD+sdpb[i-1][j-1])%MOD;
sdpb[i][j]=(sdpb[i-1][j]+dpb[i][j])%MOD;
// printf("%d %d %d\n",i,j,dpb[i][j]);
} int ans=0;
for(int i=0;i<k-1;i++) for(int j=1;j<=n;j++)
ans=(ans+1ll*sdpa[n][i]*dpb[j][k-i]%MOD*c[n-j][m-k])%MOD;
for(int i=0;i<=n;i++) for(int j=1;j<=n;j++) if(2*n-i-j>=0)
ans=(ans+1ll*dpa[i][k-1]*b[j]%MOD*c[2*n-i-j][m-k])%MOD;
printf("%d\n",ans);
}
int main(){
for(int i=0;i<=MAXN*2;i++){
c[i][0]=1;
for(int j=1;j<=i;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%MOD;
}
int qu;scanf("%d",&qu);while(qu--) solve();
return 0;
}
洛谷 P5299 - [PKUWC2018]Slay the Spire(组合数学+dp)的更多相关文章
- 洛谷 P6276 - [USACO20OPEN]Exercise P(组合数学+DP)
洛谷题面传送门 废了,又不会做/ll orz czx 写的什么神仙题解,根本看不懂(%%%%%%%%% 首先显然一个排列的贡献为其所有置换环的乘积.考虑如何算之. 碰到很多数的 LCM 之积只有两种可 ...
- [LOJ2538][PKUWC2018]Slay the Spire:DP
分析 学会新姿势!我们可以通过调整DP顺序来体现选取物品的优先顺序! 显然选取强化牌的最优策略是倍数从高到低,能选就选,最多选\(k-1\)张,选取攻击牌的最优策略是伤害从高到低,尽量少选,但最少选\ ...
- 洛谷 P5400 - [CTS2019]随机立方体(组合数学+二项式反演)
洛谷题面传送门 二项式反演好题. 首先看到"恰好 \(k\) 个极大值点",我们可以套路地想到二项式反演,具体来说我们记 \(f_i\) 为钦定 \(i\) 个点为极大值点的方案数 ...
- BZOJ.5467.[PKUWC2018]Slay the Spire(DP)
LOJ BZOJ 洛谷 哪张能力牌能乘攻击啊,太nb了叭 显然如果有能力牌,那么应该选最大的尽可能的打出\(k-1\)张. 然后下面说的期望都是乘总方案数后的,即所有情况的和.然后\(w_i\)统一用 ...
- 洛谷 P4708 - 画画(Burnside 引理+组合数学)
洛谷题面传送门 神仙题 %%%%%%%%%%%%%%%%%%%% 题解搬运人来了 首先看到本质不同(无标号)的图计数咱们可以想到 Burnside 引理,具体来说,我们枚举一个排列 \(p\),并统计 ...
- 洛谷CF809C Find a car(数位DP)
洛谷题目传送门 通过瞪眼法发现,\(a_{i,j}=(i-1)\text{ xor }(j-1)+1\). 二维差分一下,我们只要能求\(\sum\limits_{i=0}^x\sum\limits_ ...
- LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)
Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...
- 【题解】洛谷P1169 [ZJOI2007] 棋盘制作(坐标DP+悬线法)
次元传送门:洛谷P1169 思路 浙江省选果然不一般 用到一个从来没有听过的算法 悬线法: 所谓悬线法 就是用一条线(长度任意)在矩阵中判断这条线能到达的最左边和最右边及这条线的长度 即可得到这个矩阵 ...
- 洛谷 P2015 二叉苹果树(codevs5565) 树形dp入门
dp这一方面的题我都不是很会,所以来练(xue)习(xi),大概把这题弄懂了. 树形dp就是在原本线性上dp改成了在 '树' 这个数据结构上dp. 一般来说,树形dp利用dfs在回溯时进行更新,使用儿 ...
随机推荐
- 解决更新页面版本后用户需CTRL+F5强刷才能应用最新页面
设置文件永远不从缓存读取 第一步:在html文件设置文件不缓存 <!DOCTYPE html> <html lang="en" class="theme ...
- SpringCloud微服务实战——搭建企业级开发框架(四):集成SpringCloud+SpringBoot
1.在GitEgg工程的根目录,最上级父pom.xml文件中引入需要依赖的库及Maven插件,设置编码方式: <!--?xml version="1.0" encoding= ...
- stm32中的串口通信你了解多少
在基础实验成功的基础上,对串口的调试方法进行实践.硬件代码顺利完成之后,对日后调试需要用到的printf重定义进行调试,固定在自己的库函数中. b) 初始化函数定义: void USART_Confi ...
- 21.7.31 test
\(NOIP\) 测试 好久没有这种感觉能阿克的冲动了!但还是挂了分 T1 WOJ2608(模拟,拓扑排序) 签到题,直接模拟,有点像拓扑排序. 要给点打标记不然可能被某次操作中弹出多次该点导致WA ...
- JavaScript中的this对象指向理解
在JavaScript中,this不是固定不变的,它的指向取决于上下文环境,一般的,认为this指向使用它时所在的对象.主要有以下几类指向: 在方法中,this 表示该方法所属的对象. 如果单独使用, ...
- Luogu P1297 [国家集训队]单选错位 | 概率与期望
题目链接 题解: 单独考虑每一道题目对答案的贡献. 设$g_i$表示gx在第$i$道题目的答案是否正确(1表示正确,0表示不正确),则$P(g_i=1)$表示gx在第$i$道题目的答案正确的概率. 我 ...
- Django开发 X-Frame-Options to deny 报错处理
本博客已停更,请转自新博客查看 https://www.whbwiki.com/318.html 错误提示 Refused to display 'http://127.0.0.1:8000/inde ...
- robot framework error: [ ERROR ] Suite 'XXX' contains no tests or tasks.(解决方法)
robot framework 按照如下操作创建项目 一.创建项目 选择菜单栏file----->new Project Name 输入项目名称. Type 选择Directory. 二.创建测 ...
- 庆祝dotnet6,fastgithub送给你
前言 dotnet6正式发布了,fastgithub是使用dotnet开发的一款github加速器,作为开发者,无人不知github,作为github用户,fastgithub也许是你不可或缺的本机工 ...
- nio实现文件夹内容的监听
参考的博客 package com.jp.filemonitor; import java.io.IOException; import java.nio.file.FileSystems; impo ...