【LOJ】#2538. 「PKUWC2018」Slay the Spire
题解
由于强化卡都是大于1的,我们分析一下就会发现,尽可能多的用强化卡,至少用一张攻击卡,一定是每组卡牌的最优选择
所以我们把攻击卡和强化卡从大到小排序
我们设\(g[i][j]\)表示前i张卡牌里选择j张强化卡,能强化的倍数之和
如果\(j <= K - 1\)
\(g[i][j] = g[i - 1][j] + g[i - 1][j - 1] * w[i]\)
否则
\(g[i][j] = g[i - 1][j] + g[i - 1][j - 1]\)
但是如果用前i张卡牌里选择j张攻击卡,能造成个攻击之和的话,由于我们选的攻击卡越多能拿的攻击卡越多,不好dp
我们用\(f[i][j]\)表示前i张卡牌用了j张攻击卡,并且用了第i张,所有方案造成的攻击和
我们计算\(h(i)\)为选了i张攻击卡牌所造成的攻击和
我们算出来选i张攻击卡能出几个攻击卡
然后枚举最后一张出的攻击卡计算即可
最后的答案就是\(\sum_{i = 1}^{m}g[N][M - i] * h(i)\)
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#define enter putchar('\n')
#define space putchar(' ')
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define pii pair<int,int>
#define eps 1e-7
#define MAXN 3005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 998244353;
int T;
int N,M,K,fac[MAXN],invfac[MAXN],inv[MAXN],w[2][MAXN];
int g[1505][1505],f[1505][1505],h[1505],sum[1505];
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int C(int n,int m) {
if(n < m) return 0;
return mul(mul(fac[n],invfac[m]),invfac[n - m]);
}
bool cmp(int a,int b) {
return a > b;
}
void Solve() {
read(N);read(M);read(K);
for(int i = 1 ; i <= N ; ++i) read(w[1][i]);
for(int i = 1 ; i <= N ; ++i) read(w[0][i]);
sort(w[0] + 1,w[0] + N + 1,cmp);
sort(w[1] + 1,w[1] + N + 1,cmp);
f[0][0] = 0,g[0][0] = 1;
memset(sum,0,sizeof(sum));
memset(h,0,sizeof(h));
for(int i = 1 ; i <= N ; ++i) {
int t = min(i,M);
f[i][0] = f[i - 1][0],g[i][0] = g[i - 1][0];
for(int j = 1 ; j <= t ; ++j) {
f[i][j] = inc(sum[j - 1],mul(C(i - 1,j - 1),w[0][i]));
g[i][j] = g[i - 1][j];
if(K - 1 >= j) g[i][j] = inc(g[i][j],mul(g[i - 1][j - 1],w[1][i]));
else g[i][j] = inc(g[i][j],g[i - 1][j - 1]);
}
for(int j = 1 ; j <= t ; ++j) sum[j] = inc(sum[j],f[i][j]);
}
for(int c = 1 ; c <= N ; ++c) {
if(c> M) break;
int ch = K - min(K - 1,M - c);
for(int i = 1 ; i <= N ; ++i) {
h[c] = inc(h[c],mul(f[i][ch],C(N - i,c - ch)));
}
}
int ans = 0;
for(int i = 1 ; i <= M ; ++i) {
if(i > N) break;
if(M - i > N) continue;
ans = inc(ans,mul(h[i],g[N][M - i]));
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
inv[1] = 1;
for(int i = 2 ; i <= 3000 ; ++i) {
inv[i] = mul(inv[MOD % i],MOD - MOD / i);
}
fac[0] = 1,invfac[0] = 1;
for(int i = 1 ; i <= 3000 ; ++i) {
fac[i] = mul(fac[i - 1],i);
invfac[i] = mul(invfac[i - 1],inv[i]);
}
read(T);
while(T--) {
Solve();
}
}
【LOJ】#2538. 「PKUWC2018」Slay the Spire的更多相关文章
- loj #2538. 「PKUWC2018」Slay the Spire
$ \color{#0066ff}{ 题目描述 }$ 九条可怜在玩一个很好玩的策略游戏:Slay the Spire,一开始九条可怜的卡组里有 \(2n\) 张牌,每张牌上都写着一个数字\(w_i\) ...
- 【LOJ】#2541. 「PKUWC2018」猎人杀
题解 一道神仙的题>< 我们毙掉一个人后总的w的和会减少,怎么看怎么像指数算法 然而,我们可以容斥-- 设\(\sum_{i = 1}^{n} w_{i} = Sum\) 我们把问题转化一 ...
- 【LOJ】 #2540. 「PKUWC2018」随机算法
题解 感觉极其神奇的状压dp \(dp[i][S]\)表示答案为i,然后不可选的点集为S 我们每次往答案里加一个点,然后方案数是,设原来可以选的点数是y,新加入一个点后导致了除了新加的点之外x个点不能 ...
- 【LOJ】#2537. 「PKUWC2018」Minimax
题解 加法没写取模然后gg了QwQ,de了半天 思想还是比较自然的,线段树合并的维护方法我是真的很少写,然后没想到 很显然,我们有个很愉快的想法是,对于每个节点枚举它所有的叶子节点,对于一个叶子节点的 ...
- 【LOJ】#2542. 「PKUWC2018」随机游走
题解 虽然我知道minmax容斥,但是--神仙能想到把这个dp转化成一个一次函数啊= = 我们相当于求给定的\(S\)集合里最后一个被访问到的点的时间,对于这样的max的问题,我们可以用容斥把它转化成 ...
- 【LOJ】#2210. 「HNOI2014」江南乐
LOJ#2210. 「HNOI2014」江南乐 感觉是要推sg函数 发现\(\lfloor \frac{N}{i}\rfloor\)只有\(O(\sqrt{N})\)种取值 考虑把这些取值都拿出来,能 ...
- 【LOJ】#3098. 「SNOI2019」纸牌
LOJ#3098. 「SNOI2019」纸牌 显然选三个以上的连续牌可以把他们拆分成三个三张相等的 于是可以压\((j,k)\)为有\(j\)个连续两个的,有\(k\)个连续一个的 如果当前有\(i\ ...
- 【LOJ】#3103. 「JSOI2019」节日庆典
LOJ#3103. 「JSOI2019」节日庆典 能当最小位置的值一定是一个最小后缀,而有用的最小后缀不超过\(\log n\)个 为什么不超过\(\log n\)个,看了一下zsy的博客.. 假如\ ...
- 【LOJ】#3102. 「JSOI2019」神经网络
LOJ#3102. 「JSOI2019」神经网络 首先我们容易发现就是把树拆成若干条链,然后要求这些链排在一个环上,同一棵树的链不相邻 把树拆成链可以用一个简单(但是需要复杂的分类讨论)的树背包实现 ...
随机推荐
- CF916E Jamie and Tree
CF916E Jamie and Tree 题意翻译 有一棵n个节点的有根树,标号为1-n,你需要维护以下三种操作 1.给定一个点v,将整颗树的根变为v 2.给定两个点u, v,将lca(u, v)所 ...
- poj 2125 Destroying The Graph (最小点权覆盖)
Destroying The Graph http://poj.org/problem?id=2125 Time Limit: 2000MS Memory Limit: 65536K ...
- 2015/11/4用Python写游戏,pygame入门(4):获取鼠标的位置及运动
按昨天的说法,今天将开始做一个简单的游戏了. 目标是拷贝微信的飞机大战,当然拷贝完以后大家就具备自己添加不同内容的能力了. 首先是要拿到一些图片素材,熟悉使用图像处理软件和绘画的人可以自己制作,并没有 ...
- SQL语句(十八)—— 存储过程
存储过程 系统存储过程 自定义存储过程 扩展存储过程 一.创建存储过程 创建存储过程 --例1 USE SU GO Create Procedure SelProc AS Select * From ...
- ipynb to pdf
Q: 如何把jupyter notebook 转为 pdf 文档? A: 尝试了几种python包, 结果都没有成功. 包括: xhtml2pdf, 查看官方的介绍说用pandoc也是一种方法, 但是 ...
- 《java语言程序设计》初步学习——各种小Demo
发现现在的天下几乎都是java的天下啊,虽然我个人对java没什么好感,但是迫于生活压力,还是学一下吧,我关注的应该主要还是web方面,所以应该学的是 java server page(JSP),所以 ...
- 20155303 2016-2017-2 《Java程序设计》第七周学习总结
20155303 2016-2017-2 <Java程序设计>第七周学习总结 教材学习中的问题和解决过程 『问题一』:SimpleDateFormat中每个字符的含义都是什么? 『问题一解 ...
- sql server中的日期函数
DATEADD 在向指定日期加上一段时间的基础上,返回新的 datetime 值. 语法 DATEADD ( datepart , number, date ) 参数 (1) ...
- 浅析XSS与XSSI异同
浅析XSS与XSSI异同 这篇文章主要介绍了XSS与XSSI异同,跨站脚本(XSS)和跨站脚本包含(XSSI)之间的区别是什么?防御方法有什么不同?感兴趣的小伙伴们可以参考一下 Michael Cob ...
- 【codeforces】【比赛题解】#861 CF Round #434 (Div.2)
本来是rated,现在变成unrated,你说气不气. 链接. [A]k-凑整 题意: 一个正整数\(n\)的\(k\)-凑整数是最小的正整数\(x\)使得\(x\)在十进制下末尾有\(k\)个或更多 ...