洛谷 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在回溯时进行更新,使用儿 ...
随机推荐
- javascript-jquery对象的动画处理
一.显示与隐藏动画效果 1.hide(动画持续时间,easing用来指定切换效果,动画执行完毕调用函数): $("p").hide(5000,"swing",f ...
- F1西班牙大奖赛-加泰罗尼亚赛道地图及简介
背景 银石双赛结束,第二轮三连赛的最后一场将转战西班牙,第50届F1西班牙大奖赛将于本周末(正赛2020-08-15)在加泰罗尼亚赛道上演. 作为近年来F1承办季前测试的赛道,所有人都对这里再熟悉不过 ...
- JDK 8中重要的函数式接口(必知必会)
JDK 8 提供的重要函数式接口: Consumer (消费者) 功能:接收一个对象,返回void. 定义:void accept(T t) 默认方法:Consumer andThen(Consume ...
- 【UE4 C++】Tick的三种方式、异步蓝图节点
Tick的三种方式 包括 默认 Tick (Actor.Component.UMG) TimerManager 定时器 FTickableGameObject 可以写原生 Object 也可以继承UO ...
- SpringCloud微服务实战——搭建企业级开发框架(七):自定义通用响应消息及统一异常处理
平时开发过程中,无可避免我们需要处理各类异常,所以这里我们在公共模块中自定义统一异常,Spring Boot 提供 @RestControllerAdvice 注解统一异常处理,我们在GitEgg ...
- qwt使用细节
在使用QWT进行二维曲线绘制,使用方法如下: class Plot: public QwtPlot { Q_OBJECT -- } 报错:error LNK2001: 无法解析的外部符号"p ...
- Go语言核心36讲(Go语言进阶技术十一)--学习笔记
17 | go语句及其执行规则(下) 知识扩展 问题 1:怎样才能让主 goroutine 等待其他 goroutine? 我刚才说过,一旦主 goroutine 中的代码执行完毕,当前的 Go 程序 ...
- hdu 2955 Robberies(背包DP)
题意: 小偷去抢银行,他母亲很担心. 他母亲希望他被抓的概率真不超过P.小偷打算去抢N个银行,每个银行有两个值Mi.Pi,Mi:抢第i个银行所获得的财产 Pi:抢第i个银行被抓的概率 求最多能抢得多少 ...
- Linux环境下安装中山大学东校区iNode客户端
在中山大学登录校园网有两种方式,一种是连接WiFi,另一种是连接网线.这两种上网方式都需要用到NetID,但是连接网线的话还需要使用到iNode客户端(指东校区). Windows下iNode客户端的 ...
- 测试平台系列(72) 了解ApScheduler基本用法
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们调研了一下市面上 ...