loj2538 「PKUWC2018」Slay the Spire 【dp】
题目链接
题解
比较明显的是,由于强化牌倍数大于\(1\),肯定是能用强化牌尽量用强化牌
如果强化牌大于等于\(k\),就留一个位给攻击牌
所以我们将两种牌分别排序,企图计算\(F(i,j)\)表示\(i\)张强化牌选出最强的\(j\)张的所有方案的倍数和
\(G(i,j)\)表示从\(i\)张攻击牌选出最强\(j\)张的所有方案的伤害和
那么
\]
所以我们只需计算出\(F\)和\(G\)
以\(F\)为例,我们枚举选出最后一张牌是什么
那么设\(f[i][j]\)表示用了\(i\)张强化牌,最后一张是\(j\)的倍数和
同样设\(g[i][j]\)表示用了\(i\)张攻击牌,最后一张是\(j\)的伤害和
那么有
\]
\]
可用前缀和优化为\(O(n^2)\)
那么
\]
\]
总复杂度\(O(Tn^2)\)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 3005,maxm = 100005,INF = 1000000000,P = 998244353;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int n,m,K,fac[maxn],fv[maxn],inv[maxn];
int w1[maxn],w2[maxn];
int f[maxn][maxn],g[maxn][maxn];
int s[maxn];
void init(){
fac[0] = fac[1] = inv[0] = inv[1] = fv[0] = fv[1] = 1;
for (int i = 2; i <= 3000; i++){
fac[i] = 1ll * fac[i - 1] * i % P;
inv[i] = 1ll * (P - P / i) * inv[P % i] % P;
fv[i] = 1ll * fv[i - 1] * inv[i] % P;
}
}
inline int C(int n,int m){
if (n < m) return 0;
return 1ll * fac[n] * fv[m] % P * fv[n - m] % P;
}
inline int F(int x,int y){
if (x > n || x < y) return 0;
int re = 0;
for (int i = 0; i <= n; i++)
re = (re + 1ll * f[y][i] * C(n - i,x - y) % P) % P;
return re;
}
inline int G(int x,int y){
if (x > n || x < y) return 0;
int re = 0;
for (int i = 0; i <= n; i++)
re = (re + 1ll * g[y][i] * C(n - i,x - y) % P) % P;
return re;
}
inline bool cmp(const int& a,const int& b){
return a > b;
}
void work(){
sort(w1 + 1,w1 + 1 + n,cmp);
sort(w2 + 1,w2 + 1 + n,cmp);
for (int i = 0; i <= n; i++)
for (int j = 0; j <= n; j++)
f[i][j] = g[i][j] = 0;
f[0][0] = 1;
s[0] = 1;
for (int i = 1; i <= n; i++) s[i] = s[i - 1];
for (int i = 1; i <= n; i++){
for (int j = i; j <= n; j++){
f[i][j] = 1ll * w1[j] * s[j - 1] % P;
}
for (int j = 0; j < i; j++) s[j] = 0;
for (int j = i; j <= n; j++) s[j] = (s[j - 1] + f[i][j]) % P;
}
s[0] = 0;
for (int i = 1; i <= n; i++) s[i] = s[i - 1];
for (int i = 1; i <= n; i++){
for (int j = i; j <= n; j++){
g[i][j] = (1ll * w2[j] * C(j - 1,i - 1) % P + s[j - 1]) % P;
}
for (int j = 0; j < i; j++) s[j] = 0;
for (int j = i; j <= n; j++) s[j] = (s[j - 1] + g[i][j]) % P;
}
int ans = 0;
for (int i = 0; i <= min(n,m); i++){
int j = m - i; if (j < 0 || j > n) continue;
if (i < K){
ans = (ans + 1ll * F(i,i) * G(j,K - i) % P) % P;
}
else{
ans = (ans + 1ll * F(i,K - 1) * G(j,1) % P) % P;
}
}
printf("%d\n",ans);
}
int main(){
init();
int T = read();
while (T--){
n = read(); m = read(); K = read();
REP(i,n) w1[i] = read();
REP(i,n) w2[i] = read();
work();
}
return 0;
}
loj2538 「PKUWC2018」Slay the Spire 【dp】的更多相关文章
- LOJ2538. 「PKUWC2018」Slay the Spire【组合数学】
LINK 思路 首先因为式子后面把方案数乘上了 所以其实只用输出所有方案的攻击力总和 然后很显然可以用强化牌就尽量用 因为每次强化至少把下面的牌翻一倍,肯定是更优的 然后就只有两种情况 强化牌数量少于 ...
- loj #2538. 「PKUWC2018」Slay the Spire
$ \color{#0066ff}{ 题目描述 }$ 九条可怜在玩一个很好玩的策略游戏:Slay the Spire,一开始九条可怜的卡组里有 \(2n\) 张牌,每张牌上都写着一个数字\(w_i\) ...
- 【LOJ】#2538. 「PKUWC2018」Slay the Spire
题解 由于强化卡都是大于1的,我们分析一下就会发现,尽可能多的用强化卡,至少用一张攻击卡,一定是每组卡牌的最优选择 所以我们把攻击卡和强化卡从大到小排序 我们设\(g[i][j]\)表示前i张卡牌里选 ...
- 「PKUWC2018」Slay the Spire
题目链接 题意分析 这个题其实不是期望 就是一共有\(C_{2n}^m\)种情况 每一种情况选择\(k\)张牌 然后求最大攻击值的总和 我们考虑 当前抽出了选出了\(i\)张强化牌 \(m-i\)张攻 ...
- LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)
Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...
- loj2542 「PKUWC2018」随机游走 【树形dp + 状压dp + 数学】
题目链接 loj2542 题解 设\(f[i][S]\)表示从\(i\)节点出发,走完\(S\)集合中的点的期望步数 记\(de[i]\)为\(i\)的度数,\(E\)为边集,我们很容易写出状态转移方 ...
- LOJ2542. 「PKUWC2018」随机游走【概率期望DP+Min-Max容斥(最值反演)】
题面 思路 我们可以把到每个点的期望步数算出来取max?但是直接算显然是不行的 那就可以用Min-Max来容斥一下 设\(g_{s}\)是从x到s中任意一个点的最小步数 设\(f_{s}\)是从x到s ...
- Loj #2542. 「PKUWC2018」随机游走
Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...
- 「PKUWC2018」随机游走(min-max容斥+FWT)
「PKUWC2018」随机游走(min-max容斥+FWT) 以后题目都换成这种「」形式啦,我觉得好看. 做过重返现世的应该看到就想到 \(min-max\) 容斥了吧. 没错,我是先学扩展形式再学特 ...
随机推荐
- oracle 数据库的详细安装教程
由于oracle数据库比较大 所以安装的时候比较慢是目前装的最大的软件了吧 而且如果装崩了 可能还会重装系统 不过比较幸运 一次就装好 1.需要去官网下载 https://www.oracle.co ...
- 零基础学Python之结构化数据(附详细的代码解释和执行结果截图)
3结构化数据 字典(查找表).集合.元组.列表 3.1字典 是有两列任意多行的表,第一列存储一个键,第二列存储一个值. 它存储键/值对,每个唯一的键有一个唯一与之关联的值.(类似于映射.表) 它不会维 ...
- java基础---类加载和对象创建过程
类中可以存在的成员: class A{ 静态成员变量: 非静态成员变量: 静态函数: 非静态函数: 构造函数 A(..){...} 静态代码块 static{...} 构造代码块 {...} } 类加 ...
- 基于Python的信用评分卡模型分析(二)
上一篇文章基于Python的信用评分卡模型分析(一)已经介绍了信用评分卡模型的数据预处理.探索性数据分析.变量分箱和变量选择等.接下来我们将继续讨论信用评分卡的模型实现和分析,信用评分的方法和自动评分 ...
- 基于C#的机器学习--贝叶斯定理-执行数据分析解决肇事逃逸之谜
贝叶斯定理-执行数据分析解决肇事逃逸之谜 在这一章中,我们将: 应用著名的贝叶斯定理来解决计算机科学中的一个非常著名的问题. 向您展示如何使用贝叶斯定理和朴素贝叶斯来绘制数据,从真值表中发现异常值 ...
- ifconfig命令详情
基础命令学习目录首页 原文链接:https://blog.csdn.net/weixin_37886382/article/details/79716879 许多windows非常熟悉ipconfig ...
- Scrum立会报告+燃尽图(Final阶段第一次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2480 项目地址:https://coding.net/u/wuyy694 ...
- sprint会议1
昨天:进行第一次站立会议,讨论冲刺阶段,目标,任务认领,制作索引卡. 今天:准备查找安卓APP开发的有关资料,安装有关软件. 遇到的问题:对这方面毫无了解,不知道怎么开始,从哪开始,完全没经验.
- HDU 4745 Two Rabbits 区间dp_回文序列
题目链接: http://blog.csdn.net/scnu_jiechao/article/details/11759333 Two Rabbits Time Limit: 10000/5000 ...
- 第三次作业---excel导入数据库及显示
好吧首先承认这次作业失败了,而且我并不知道原因.另外,我也没有采用PowerDesigner 设计所需要的数据库,代码就用了全部的时间.感觉自己就像一个刚学会爬着走路的小孩去参加一百一十米跨栏,能不能 ...