loj #2538. 「PKUWC2018」Slay the Spire
$ \color{#0066ff}{ 题目描述 }$
九条可怜在玩一个很好玩的策略游戏:Slay the Spire,一开始九条可怜的卡组里有 \(2n\) 张牌,每张牌上都写着一个数字\(w_i\),一共有两种类型的牌,每种类型各 \(n\) 张:
- 攻击牌:打出后对对方造成等于牌上的数字的伤害。
- 强化牌:打出后,假设该强化牌上的数字为\(x\),则其他剩下的攻击牌的数字都会乘上 \(x\)。保证强化牌上的数字都大于 1。
现在九条可怜会等概率随机从卡组中抽出 \(m\) 张牌,由于费用限制,九条可怜最多打出 \(k\) 张牌,假设九条可怜永远都会采取能造成最多伤害的策略,求她期望造成多少伤害。
假设答案为 \(\text{ans}\),你只需要输出
\(\left (\text{ans}\times \frac{(2n)!}{m!(2n-m)!}\right) ~\bmod 998244353\)
即可
其中 \(x!\) 表示 \(\prod_{i=1}^{x}i\),特别地,\(0!=1\)
\(\color{#0066ff}{输入格式}\)
第一行一个正整数 \(T\) 表示数据组数
接下来对于每组数据:
第一行三个正整数 \(n,m,k\)
第二行 \(n\) 个正整数 \(w_i\),表示每张强化牌上的数值。
第三行 \(n\) 个正整数 \(w_i\),表示每张攻击牌上的数值。
\(\color{#0066ff}{输出格式}\)
输出 \(T\) 行,每行一个非负整数表示每组数据的答案。
\(\color{#0066ff}{输入样例}\)
2
2 3 2
2 3
1 2
10 16 14
2 3 4 5 6 7 8 9 10 11
1 2 3 4 5 6 7 8 9 10
\(\color{#0066ff}{输出样例}\)
19
253973805
\(\color{#0066ff}{数据范围与提示}\)
对于所有数据,有 \(1\leq k\leq m\leq 2n\leq 3\times 10^3\),且\(1\leq w_i\leq 10^8\)。
保证强化牌上的数字都大于 1。
以下 \((\sum 2n)\) 表示对于输入中所有数据的\(2n\)的和。
对于 \(10\%\) 的数据,有 \(1\leq \sum 2n\leq 10\)
对于 \(20\%\) 的数据,有 \(1\leq \sum 2n\leq 100\)
对于 \(30\%\) 的数据,有 \(1\leq \sum 2n\leq 500\)
另有 \(20\%\) 的数据,满足所有攻击牌的数值相同。
另有 \(20\%\) 的数据,满足 \(m=k\)。
对于 \(100\%\) 的数据,有 \(1\leq \sum 2n\leq 30000\)
\(\color{#0066ff}{题解}\)
假如说我们已经有了m张牌,现在考虑怎么打出k张牌会最优呢
首先,一定是先打强化牌再打攻击牌最优,不解释
那么到底选多少攻击牌和强化牌呢
首先,我们先把m张牌分两类从大到小排序,那么肯定是选两类牌的一个前缀
比如,强化3 2, 攻击a b,\(k=3\)
那么显然\(2*3*a=3a+3a>3a+3b\)
因此,我们要尽可能多的选强化牌,剩下的选攻击牌
我们设状态\(f[i][j][0/1]\)表示强化牌中,前i张选j张,第i张选不选(这是为了统计方案不重不漏)的贡献
举个锤子,比如强化牌5 4 3 2,那么\(f[4][3][1]\)就是\(2 * 3 * 5+2 * 4 * 5+2 * 3 * 4\),就是所有合法贡献的和
同理\(g[i][j][0/1]\)是针对ATK的DP
转移很容易,\(O(n^2)\)
f[0][0][0] = 1;
for(int i = 1; i <= n; i++) {
for(int j = 0; j <= i; j++) {
if(j >= 1) {
f[i][j][1] = ((f[i - 1][j - 1][1] + f[i - 1][j - 1][0]) % mod * STG[i] % mod);
g[i][j][1] = ((g[i - 1][j - 1][1] + g[i - 1][j - 1][0]) % mod + ATK[i] * C(i - 1, j - 1) % mod) % mod;
}
f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1]);
g[i][j][0] = (g[i - 1][j][0] + g[i - 1][j][1]);
}
}
之后我们开始统计方案
为了不重不漏,我们分别在两个序列枚举端点i和j
首先考虑已有的m张牌中,强化牌\(\ge k-1\)张
那么我们肯定是选前\(k-1\)张大的强化牌和1张攻击牌, 剩下的\(m-k\)放在其它位置
\(f[i][k-1][1]*g[j][1][1]*C_{2n -i-j}^{m-k}\)
如果没有那么多,只只有\(w,w<k-1\)张,我们肯定都选,然后剩下的\(k-w\)张是攻击牌,注意,这时候剩下的\(m-k\)张牌必须只能是攻击牌, 因为强化牌不够!
\(f[i][w][1]*g[j][k-w][1]*C_{n-j}^{m-k}\)
注意当不选强化牌的时候要特判一下,即\(k=1\)的时候,还有\(k\ne 1\)时不选强化牌的情况,直接统计方案的话因为f是0,所以最后就是0,显然不对了,单独算一下就行
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int mod = 998244353;
const int maxn = 3030;
LL f[maxn][maxn][2], g[maxn][maxn][2];
LL ATK[maxn], STG[maxn], fac[maxn << 1], inv[maxn << 1];
int n, m, k;
LL ksm(LL x, LL y) {
LL re = 1LL;
while(y) {
if(y & 1) re = re * x % mod;
x = x * x % mod;
y >>= 1;
}
return re;
}
LL C(int x, int y) {
if(x < y) return 0;
return fac[x] * inv[y] % mod * inv[x - y] % mod;
}
void predoit() {
std::sort(STG + 1, STG + n + 1, std::greater<LL>());
std::sort(ATK + 1, ATK + n + 1, std::greater<LL>());
f[0][0][0] = 1;
for(int i = 1; i <= n; i++) {
for(int j = 0; j <= i; j++) {
if(j >= 1) {
f[i][j][1] = ((f[i - 1][j - 1][1] + f[i - 1][j - 1][0]) % mod * STG[i] % mod);
g[i][j][1] = ((g[i - 1][j - 1][1] + g[i - 1][j - 1][0]) % mod + ATK[i] * C(i - 1, j - 1) % mod) % mod;
}
f[i][j][0] = (f[i - 1][j][0] + f[i - 1][j][1]);
g[i][j][0] = (g[i - 1][j][0] + g[i - 1][j][1]);
}
}
}
void fuck() {
LL ans = 0;
for(int i = k - 1; i <= n; i++)
for(int j = 1; j <= n; j++)
(ans += f[i][k - 1][1] * g[j][1][1] % mod * C((n << 1) - i - j, m - k) % mod) %= mod;
for(int w = 1; w <= k - 2; w++) {
LL tot = 0;
for(int i = 1; i <= n; i++) (tot += f[i][w][1]) %= mod;
for(int i = 1; i <= n; i++) (ans += tot * g[i][k - w][1] % mod * C(n - i, m - k) % mod) %= mod;
}
for(int i = 1; i <= n; i++) (ans += g[i][k][1] * C(n - i, m - k) % mod) %= mod;
printf("%lld\n", ans);
}
void work() {
LL ans = 0;
for(int i = 1; i <= n; i++) (ans += ATK[i] * C((n << 1) - i, m - k) % mod) %= mod;
printf("%lld\n", ans);
}
int main() {
fac[0] = 1;
for(LL i = 1; i <= 6000; i++) fac[i] = i * fac[i - 1] % mod;
inv[6000] = ksm(fac[6000], mod - 2);
for(LL i = 5999; i >= 0; i--) inv[i] = (i + 1) * inv[i + 1] % mod;
for(int T = in(); T --> 0;) {
n = in(), m = in(), k = in();
for(int i = 1; i <= n; i++) STG[i] = in();
for(int i = 1; i <= n; i++) ATK[i] = in();
predoit();
if(k == 1) work();
else fuck();
}
return 0;
}
loj #2538. 「PKUWC2018」Slay the Spire的更多相关文章
- 【LOJ】#2538. 「PKUWC2018」Slay the Spire
题解 由于强化卡都是大于1的,我们分析一下就会发现,尽可能多的用强化卡,至少用一张攻击卡,一定是每组卡牌的最优选择 所以我们把攻击卡和强化卡从大到小排序 我们设\(g[i][j]\)表示前i张卡牌里选 ...
- LOJ2538. 「PKUWC2018」Slay the Spire【组合数学】
LINK 思路 首先因为式子后面把方案数乘上了 所以其实只用输出所有方案的攻击力总和 然后很显然可以用强化牌就尽量用 因为每次强化至少把下面的牌翻一倍,肯定是更优的 然后就只有两种情况 强化牌数量少于 ...
- loj2538 「PKUWC2018」Slay the Spire 【dp】
题目链接 loj2538 题解 比较明显的是,由于强化牌倍数大于\(1\),肯定是能用强化牌尽量用强化牌 如果强化牌大于等于\(k\),就留一个位给攻击牌 所以我们将两种牌分别排序,企图计算\(F(i ...
- 「PKUWC2018」Slay the Spire
题目链接 题意分析 这个题其实不是期望 就是一共有\(C_{2n}^m\)种情况 每一种情况选择\(k\)张牌 然后求最大攻击值的总和 我们考虑 当前抽出了选出了\(i\)张强化牌 \(m-i\)张攻 ...
- Loj #2542. 「PKUWC2018」随机游走
Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...
- loj#2537. 「PKUWC2018」Minimax
题目链接 loj#2537. 「PKUWC2018」Minimax 题解 设\(f_{u,i}\)表示选取i的概率,l为u的左子节点,r为u的子节点 $f_{u,i} = f_{l,i}(p \sum ...
- LOJ #2541「PKUWC2018」猎人杀
这样$ PKUWC$就只差一道斗地主了 假装补题补完了吧..... 这题还是挺巧妙的啊...... LOJ # 2541 题意 每个人有一个嘲讽值$a_i$,每次杀死一个人,杀死某人的概率为$ \fr ...
- LOJ #2542「PKUWC2018」随机游走
$ Min$-$Max$容斥真好用 $ PKUWC$滚粗后这题一直在$ todolist$里 今天才补掉..还要更加努力啊.. LOJ #2542 题意:给一棵不超过$ 18$个节点的树,$ 5000 ...
- LOJ 2542 「PKUWC2018」随机游走 ——树上高斯消元(期望DP)+最值反演+fmt
题目:https://loj.ac/problem/2542 可以最值反演.注意 min 不是独立地算从根走到每个点的最小值,在点集里取 min ,而是整体来看,“从根开始走到点集中的任意一个点就停下 ...
随机推荐
- 成都国嵌-嵌入式linux必修实验手册…
emouse收集整理,转载请注明: emouse的技术专栏 博客园:http://www.cnblogs.com/emouse/ CSDN:http://blog.csdn.net/haozi_198 ...
- C语言之随机数和字符串输入输出
一.随机数产生函数 1.需要加入头文件 #include<stdlib.h> 和 #include<time.h> 2.Rand是伪随机数产生器,每次调用rand产生的随机数是 ...
- iPython notebook 安装使用
pip install jupyter jupyter notebook --allow-root
- IIS设置Access-Control-Allow-Origin
打开iis,找到“HTTP响应标头”点进去, 在右侧可以看到添加,然后添加如下标头即可Access-Control-Allow-Headers:Content-Type, api_key, Autho ...
- solrcloud使用问题记录
Solr Ping query caused exception: undefined field text [java] view plaincopy <span style="fo ...
- C. Ray Tracing——披着搜索外衣的扩展欧几里得
[题目大意] 给你一个n*m的矩形,光线从(0,0)出发,沿右上方向以每秒根号2米的速度运动,碰到矩形边界就会反弹(符合物理规律的反弹),询问k个点,这些点都在矩形内部且不在矩形边界上,求光经过这些点 ...
- 二项分布 , 多项分布, 以及与之对应的beta分布和狄利克雷分布
1. 二项分布与beta分布对应 2. 多项分布与狄利克雷分布对应 3. 二项分布是什么?n次bernuli试验服从 二项分布 二项分布是N次重复bernuli试验结果的分布. bernuli实验是什 ...
- Windows下用Nginx配置遇到的问题
Nginx是一款轻量级的web服务器/反向代理服务器,更详细的释义自己百度了.目前国内像新浪.网易等都在使用它.先说下我的服务器软件环境: 系统:Windows Server + IIS + ngin ...
- codefirst 最新策略
http://www.yunjuu.com/info/76058.html 在原有数据库中使用 CodeFirst ,除了第一次添加实体后要立即执行一次 Enable-Migrations add-m ...
- Entity Framework在不同数据库下的配置
http://blog.csdn.net/weiky626/article/details/17068593 http://blog.csdn.net/niewq/article/details/41 ...