1 条题解
-
0
自动搬运
来自洛谷,原作者为

TheLostWeak
**搬运于
2025-08-24 22:09:15,当前版本为作者最后更新于2019-12-19 09:12:43,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
大致题意: 有张强化牌和张攻击牌,每张牌有一个权值(强化牌的权值大于),每张强化牌能使所有攻击牌的权值乘上这张强化牌的权值,每张攻击牌造成的伤害等于这张攻击牌的权值。现在,以等概率抽出张牌,并以最优策略使用其中至多张牌造成最大的伤害。求所有情况下,造成伤害总和。
何为最优策略
这道题看似毫无头绪,因此,我们先要好好推一推性质。
假设现在我们已经选好了张牌,那么最优策略是什么?
首先,如果我们已经确定要用张强化牌和张攻击牌,那么根据贪心的想法,肯定是先使用权值最大的张强化牌,再使用权值最大的张攻击牌。
因此我们把和分别从大到小排序。
同时,同样依据贪心,我们可以知道答案就是强化牌的乘积乘上攻击牌之和。
然后我们考虑,在什么情况下,把第张攻击牌换成第张强化牌,与原先答案相比不会变劣。
原先答案是:
变化后的答案是:
则两式相减,即为答案的变化量,也就是:
$$(a_{x+1}-1)\cdot(\prod_{i=1}^xa_i\cdot\sum_{i=1}^{y-1}b_i)-(\prod_{i=1}^xa_i)\cdot b_y $$当变化后答案不变劣,说明变化量,即:
$$(a_{x+1}-1)\cdot(\prod_{i=1}^xa_i\cdot\sum_{i=1}^{y-1}b_i)\ge(\prod_{i=1}^xa_i)\cdot b_y $$我们把式子中的去掉,就得到:
由于题目中说明,强化牌权值大于,所以。
而在时,因为数组经过了从大到小排序,所以肯定大于等于。
所以我们可以发现,在时,是始终成立的。
也就是说,在保有至少一张攻击牌的前提下,肯定是尽量选择强化牌会更优。
这么一来,这道题一下就可做得多了。
预处理
在正式开始解题之前,我们还需要进行预处理,定义几个变量。
设表示在前张强化牌中选择张且第张被选中的所有情况下,这张牌的乘积之和,表示在前张攻击牌中选择张且第张被选中的所有情况下,这张牌的和之和。
同时,定义$f_{i,j,1}=\sum_{x=1}^if_{x,j,0},g_{i,j,1}=\sum_{x=1}^ig_{x,j,0}$来辅助转移。
则不难发现,有转移方程:
注意,的转移中,表示在个数中选择个数的方案,即从转移到共有种情况,而每种情况卡牌权值和加上了,就相当于共加上了。
至于这些东西究竟有什么用,待会儿你就会知道了。
组合数学
接下来,就是分类讨论+推式子啦。
第一类:当张牌中,强化牌的数量小于张时。
此时必然是选上所有的强化牌,然后选上权值最大的一些攻击牌。
不难发现,其实等于张时也符合这一类情况的操作方案,但为了方便起见,我们把等于的情况放入另一类情况中中。
对于这一种情况,我们枚举分别表示强化牌有张和最后被选中的攻击牌是第张。
在强化牌中选择张的所有合法情况下的乘积之和,其实就是。
而强化牌中选择张,攻击牌中就要选择张,又由于最后被选中的攻击牌是第张,所以所有合法情况下攻击牌的和之和,其实就是。
而若要最终选出的张牌是这张牌,就剩余张牌就需要满足:
- 不存在强化牌。
- 所有攻击牌都必须在第张之后,否则选这张攻击牌肯定比选第张优。
因此方案数就是。
总结一下,就是枚举,然后每次答案加上。
第二类:当张强化牌中,强化牌的数量大于等于时。
此时必然是选上权值最大的张强化牌,然后选上权值最大的一张攻击牌。
对于这一种情况,我们枚举分别表示最后被选中的强化牌是第张和被选中的攻击牌是第张。
在前张强化牌中选择张,且第张必选,所有合法情况下的乘积之和,其实就是。
选择第张攻击牌,攻击牌之和其实就是第张攻击牌的权值,也就是。
而若要最终选出的张牌是这张牌,就剩余张牌就需要满足:
- 所有强化牌都必须在第张之后。
- 所有攻击牌都必须在第张之后。
因此方案数就是。
总结一下,就是枚举,然后每次答案加上。
具体实现可见代码。
代码
#include<bits/stdc++.h> #define Tp template<typename Ty> #define Ts template<typename Ty,typename... Ar> #define Reg register #define RI Reg int #define Con const #define CI Con int& #define I inline #define W while #define N 6000 #define X 998244353 using namespace std; int n,m,k,a[N+5],b[N+5],C[N+5][N+5],f[N+5][N+5][2],g[N+5][N+5][2]; I bool cmp(CI x,CI y) {return x>y;} int main() { RI i,j;for(C[0][0]=i=1;i<=N;++i) for(C[i][0]=j=1;j<=i;++j) C[i][j]=(C[i-1][j-1]+C[i-1][j])%X;//预处理组合数 RI Tt,ans;scanf("%d",&Tt);W(Tt--) { for(scanf("%d%d%d",&n,&m,&k),ans=0,i=1;i<=n;++i) scanf("%d",a+i); for(i=1;i<=n;++i) scanf("%d",b+i);sort(a+1,a+n+1,cmp),sort(b+1,b+n+1,cmp);//从大到小排序 for(f[0][0][0]=f[0][0][1]=i=1;i<=n;++i) for(f[i][0][1]=j=1;j<=i;++j)//预处理f f[i][j][0]=1LL*a[i]*f[i-1][j-1][1]%X,f[i][j][1]=(f[i][j][0]+f[i-1][j][1])%X; for(i=1;i<=n;++i) for(j=1;j<=i;++j)//预处理g g[i][j][0]=(1LL*b[i]*C[i-1][j-1]+g[i-1][j-1][1])%X,g[i][j][1]=(g[i][j][0]+g[i-1][j][1])%X; for(i=0;i<k-1;++i) for(j=1;j<=n;++j) ans=(1LL*f[n][i][1]*g[j][k-i][0]%X*C[n-j][m-k]+ans)%X;//当强化牌数量小于k-1时 for(i=0;i<=n;++i) for(j=1;j<=n;++j) ans=(1LL*f[i][k-1][0]*b[j]%X*C[2*n-i-j][m-k]+ans)%X;//当强化拍数量大于等于k-1时 printf("%d\n",ans);//输出答案 }return 0; }
- 1
信息
- ID
- 4284
- 时间
- 1000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者