题面传送门

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. AIApe问答机器人Scrum Meeting 4.29

    Scrum Meeting 4 日期:2021年4月29日 会议主要内容概述:汇报两日工作,讨论任务优先级. 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 李明 ...

  2. 微信小程序的实现原理

    一.背景 网页开发,渲染线程和脚本是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应的原因,本质就是我们常说的 JS 是单线程的 而在小程序中,选择了 Hybrid 的渲染方式,将视图层和逻 ...

  3. 零基础入门c语言函数之递归函数

    今天来总结一下关于递归函数的使用方面的问题. 递归函数就是在函数使用的时候自己调用自己,层层调用,来实现你想要的功能. 有两个最常用的例子,我们来写一下. (1)计算阶乘 #include int f ...

  4. Taylor公式原来可以这么简单

    1.Taylor公式 解决:含有高阶导数的中值定理或定积分.极限运算等题目 条件:f(x)在x=x0领域内(n+1)阶可导 结论:f(x)=Pn(x)+Rn(x) 2.x和x0的取值 3.Taylor ...

  5. Less-5闯关失败

    进行第五关的通关还是用之前的方式进行测试以及判断是什么类型的注入.通过判断我们不难发现是字符型注入.但是出了问题,我们会发现按照原来的步骤进行注入都会返回"You are in " ...

  6. 国产Linux服务器-Jexus的初步使用

    题记:年末研究了一些关于Net跨平台的东西,没错,就是Jexus,就是Windows下面的IIS. 官网:https://www.jexus.org/ 先看看官网的解释再说其他的问题,Jexus就是L ...

  7. 源码解析-Abp vNext丨分布式事件总线DistributedEventBus

    前言 上一节咱们讲了LocalEventBus,本节来讲本地事件总线(DistributedEventBus),采用的RabbitMQ进行实现. Volo.Abp.EventBus.RabbitMQ模 ...

  8. 解决create-react-app 后 npm start or yarn start 中出现 的webpack版本问题

    解决create-react-app 后 npm start or yarn start 中出现 的webpack版本问题 错误提示信息 There might be a problem with t ...

  9. .net core api 请求实现接口幂等性

    简单实现接口幂等性,根据参数的hascode实现: 参数介绍  WaitMillisecond : 请求等待毫秒数 CacheMillisecond:请求结果缓存毫秒数 参数具体使用场景 WaitMi ...

  10. dart系列之:dart语言中的特殊操作符

    dart系列之:dart语言中的特殊操作符 目录 简介 普通操作符 类型测试操作符 条件运算符 级联符号 类中的自定义操作符 总结 简介 有运算就有操作符,dart中除了普通的算术运算的操作符之外,还 ...