题面传送门

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)的更多相关文章

  1. 洛谷 P6276 - [USACO20OPEN]Exercise P(组合数学+DP)

    洛谷题面传送门 废了,又不会做/ll orz czx 写的什么神仙题解,根本看不懂(%%%%%%%%% 首先显然一个排列的贡献为其所有置换环的乘积.考虑如何算之. 碰到很多数的 LCM 之积只有两种可 ...

  2. [LOJ2538][PKUWC2018]Slay the Spire:DP

    分析 学会新姿势!我们可以通过调整DP顺序来体现选取物品的优先顺序! 显然选取强化牌的最优策略是倍数从高到低,能选就选,最多选\(k-1\)张,选取攻击牌的最优策略是伤害从高到低,尽量少选,但最少选\ ...

  3. 洛谷 P5400 - [CTS2019]随机立方体(组合数学+二项式反演)

    洛谷题面传送门 二项式反演好题. 首先看到"恰好 \(k\) 个极大值点",我们可以套路地想到二项式反演,具体来说我们记 \(f_i\) 为钦定 \(i\) 个点为极大值点的方案数 ...

  4. BZOJ.5467.[PKUWC2018]Slay the Spire(DP)

    LOJ BZOJ 洛谷 哪张能力牌能乘攻击啊,太nb了叭 显然如果有能力牌,那么应该选最大的尽可能的打出\(k-1\)张. 然后下面说的期望都是乘总方案数后的,即所有情况的和.然后\(w_i\)统一用 ...

  5. 洛谷 P4708 - 画画(Burnside 引理+组合数学)

    洛谷题面传送门 神仙题 %%%%%%%%%%%%%%%%%%%% 题解搬运人来了 首先看到本质不同(无标号)的图计数咱们可以想到 Burnside 引理,具体来说,我们枚举一个排列 \(p\),并统计 ...

  6. 洛谷CF809C Find a car(数位DP)

    洛谷题目传送门 通过瞪眼法发现,\(a_{i,j}=(i-1)\text{ xor }(j-1)+1\). 二维差分一下,我们只要能求\(\sum\limits_{i=0}^x\sum\limits_ ...

  7. LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)

    Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...

  8. 【题解】洛谷P1169 [ZJOI2007] 棋盘制作(坐标DP+悬线法)

    次元传送门:洛谷P1169 思路 浙江省选果然不一般 用到一个从来没有听过的算法 悬线法: 所谓悬线法 就是用一条线(长度任意)在矩阵中判断这条线能到达的最左边和最右边及这条线的长度 即可得到这个矩阵 ...

  9. 洛谷 P2015 二叉苹果树(codevs5565) 树形dp入门

    dp这一方面的题我都不是很会,所以来练(xue)习(xi),大概把这题弄懂了. 树形dp就是在原本线性上dp改成了在 '树' 这个数据结构上dp. 一般来说,树形dp利用dfs在回溯时进行更新,使用儿 ...

随机推荐

  1. SpringCloud微服务实战——搭建企业级开发框架(四):集成SpringCloud+SpringBoot

    1.在GitEgg工程的根目录,最上级父pom.xml文件中引入需要依赖的库及Maven插件,设置编码方式: <!--?xml version="1.0" encoding= ...

  2. 【数据结构与算法Python版学习笔记】图——拓扑排序 Topological Sort

    概念 很多问题都可转化为图, 利用图算法解决 例如早餐吃薄煎饼的过程 制作松饼的难点在于知道先做哪一步.从图7-18可知,可以首先加热平底锅或者混合原材料.我们借助拓扑排序这种图算法来确定制作松饼的步 ...

  3. 【二食堂】Alpha - Scrum Meeting 2

    Scrum Meeting 2 例会时间:4.11 20:00 - 20:30 进度情况 组员 今日进度 明日任务4.12不开会 李健 1. 学习并成功搭建简单的网页issue2. 学习JS基础知识i ...

  4. matlab添加永久路径

    addpath('D:\MATLAB6p5\toolbox\svm'); 临时添加路径,不能添加子目录 addpath(genpath('D:\MATLAB6p5\toolbox\svm'));临时添 ...

  5. Treevalue(0x01)——功能概述

    TreeValue--一个通用树状数据结构与函数计算库 Treevalue v1.0.0版本已经于2021年10月24日正式发布,欢迎下载体验:opendilab / treevalue. 这算是tr ...

  6. Spring Cache 带你飞(一)

    Spring 3.1 版本引入基于 annotation 的 cache 技术,提供了一套抽象的缓存实现方案,通过注解方式使用缓存,基于配置的方式灵活使用不同缓存组件.代码具有相当的灵活性和扩展性,本 ...

  7. best-time-to-buy-and-sell-stock-ii leetcode C++

    Say you have an array for which the i th element is the price of a given stock on day i. Design an a ...

  8. 字符串可以这样加索引,你知吗?《死磕MySQL系列 七》

    系列文章 三.MySQL强人"锁"难<死磕MySQL系列 三> 四.S 锁与 X 锁的爱恨情仇<死磕MySQL系列 四> 五.如何选择普通索引和唯一索引&l ...

  9. 使用psftp向服务器上传文件

    老师刚才说想用psftp上传文件到服务器,我之前没听过,学了一下,总结下.我们用PSFTP主要也就是上传和下载. PSFTP是PuTTY SFTP客户端,用于本地与服务器间安全传输文件(使用SSH连接 ...

  10. 使用Charles 弱网测试

    打开Charles->Proxy→Throttle Settings 1.可以选择不通的网络类型,对于网络的配置一般修改下上行下行即可 2.网络设置各字段解释 bandwidth -- 带宽,即 ...