PKUSC2018 Slay The Spire
有攻击牌和强化牌各 $n$ 张,强化牌可以让之后所有攻击牌攻击力乘一个大于 $1$ 的系数,攻击牌可以造成伤害
求所有“抽出 $m$ 张然后打 $k$ 张”能造成的伤害之和
$k,m,2n \leq 3000$
sol:
冷静一下,发现强化牌肯定要打完,因为一张攻击力最大的攻击牌就相当于没强化的强化牌
讨论一下抽到了几张强化牌
假设抽到了 $i$ 张强化牌,$k-i$ 张攻击牌
如果 $i < k$ 直接强化全打然后攻击就完事了,如果 $i \geq k$ 的话打最大的 $k-1$ 张强化和最大的一张攻击
由此可以 $dp$
设 $f_i$ 为 $i$ 张强化牌最多能扩的倍数,枚举当前抽到的强化牌 $j$,则
当 $i < k$ 时,$f_i = f_{i-1} + w_j \times f_j$
else, $f_i = f_i+f_{i-1}$
设 $g_i$ 为选了 $i$ 张攻击牌不翻倍的最大攻击力,枚举当前抽到的攻击牌 $j$,则
$g_i = g_{i-1} + C_{i-1}^{j-1} \times w_j + c$ (当 $i \leq (m-k+1)$ 时 $c=0$,$i>(m-k+1)$ 时 $c=g_{i-1}$)
答案就是 $\sum\limits_{i=0}^m f_i \times g_{m-i}$
第一个转移显然是按倍数从大到小排序,第二个需要把攻击力从小到大排序,
第一个转移,不管是怎么转移过来的,每张强化牌的贡献都是一样的,
第二个算每张牌贡献的时候,$c$ 标注了这张攻击牌打完之后还能不能再打别的攻击牌,如果不能打就是 $0$,能打的话要求跟他一起打的尽量大,这样转移能保证我们打的是一段尽量大的攻击牌
#include<bits/stdc++.h>
#define LL long long
#define rep(i,s,t) for(register int i = (s),i##end = (t); i <= i##end; ++i)
#define dwn(i,s,t) for(register int i = (s),i##end = (t); i >= i##end; --i)
using namespace std; const int mod = ;
inline int read()
{
int x=,f=;char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
for(;isdigit(ch);ch=getchar())x=*x+ch-'';
return x*f;
}
bool cmp(int a, int b) { return a > b; }
LL fac[], inv[];
int T, n, m, k, ans, f[], g[], w[];
LL C(int n, int m) { return fac[n] * inv[m] % mod * inv[n - m] % mod; }
int main() {
fac[] = fac[] = inv[] = inv[] = ;
for (int i = ; i <= ; i++) {
fac[i] = fac[i - ] * i % mod;
inv[i] = ((LL)mod - mod / i) * inv[mod % i] % mod;
}
for (int i = ; i <= ; i++) inv[i] = inv[i] * inv[i - ] % mod;
T = read();
while (T--) {
n = read(), m = read(), k = read();
for (int i = ; i <= n; i++) w[i] = read();
sort(w + , w + n + , cmp);
for (int i = ; i <= max(n, m); i++) f[i] = ;
f[] = ;
for (int i = ; i <= n; i++)
for (int j = min(m, i); j >= ; j--)
if (j <= k - )
f[j] = (f[j] + (LL)f[j - ] * w[i] % mod) % mod;
else
f[j] = (f[j] + f[j - ]) % mod;
for (int i = ; i <= n; i++) w[i] = read();
sort(w + , w + n + );
for (int i = ; i <= max(n, m); i++) g[i] = ;
for (int i = ; i <= n; i++)
for (int j = min(m, i); j >= ; j--)
if (j <= m - (k - ))
g[j] = (g[j] + (LL)C(i - , j - ) * w[i] % mod) % mod;
else
g[j] = ((g[j] + g[j - ]) % mod + (LL)C(i - , j - ) * w[i] % mod) % mod;
ans = ;
for (int i = ; i <= m; i++) ans = (ans + (LL)f[i] * g[m - i] % mod) % mod;
printf("%d\n", ans);
}
return ;
}
当然比赛不会真的这么写...老老实实用两维状态前缀和优化,考后自然要选择好一点的写法
PKUSC2018 Slay The Spire的更多相关文章
- BZOJ 5467 Slay the Spire
BZOJ 5467 Slay the Spire 我的概率基础也太差了.jpg 大概就是这样,因为强化牌至少翻倍,所以打出的牌必定是全部的强化牌或者$k-1$个强化牌,然后剩余的机会打出最大的几个攻击 ...
- LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)
Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...
- loj #2538. 「PKUWC2018」Slay the Spire
$ \color{#0066ff}{ 题目描述 }$ 九条可怜在玩一个很好玩的策略游戏:Slay the Spire,一开始九条可怜的卡组里有 \(2n\) 张牌,每张牌上都写着一个数字\(w_i\) ...
- BZOJ.5467.[PKUWC2018]Slay the Spire(DP)
LOJ BZOJ 洛谷 哪张能力牌能乘攻击啊,太nb了叭 显然如果有能力牌,那么应该选最大的尽可能的打出\(k-1\)张. 然后下面说的期望都是乘总方案数后的,即所有情况的和.然后\(w_i\)统一用 ...
- [PKUWC2018] Slay the spire
Description 现在有 \(n\) 张强化牌和 \(n\) 张攻击牌: 攻击牌:打出后对对方造成等于牌上的数字的伤害. 强化牌:打出后,假设该强化牌上的数字为 \(x\),则其他剩下的攻击牌的 ...
- 题解-PKUWC2018 Slay the Spire
Problem loj2538 Solution 在考场上当然要学会写暴力,考虑如果手上已经有了\(a\)张攻击牌和\(b\)张强化牌: 首先强化牌会在攻击牌之前用(废话),其次要将两种牌分别从大往小 ...
- LOJ2538 PKUWC2018 Slay the Spire DP
传送门 不想放题面了,咕咕咕咕咕 这个期望明明是用来吓人的,其实要算的就是所有方案的最多伤害的和. 首先可以知道的是,能出强化牌就出强化牌(当然最后要留一张攻击牌出出去),且数字尽量大 所以说在强化牌 ...
- LOJ2538. 「PKUWC2018」Slay the Spire【组合数学】
LINK 思路 首先因为式子后面把方案数乘上了 所以其实只用输出所有方案的攻击力总和 然后很显然可以用强化牌就尽量用 因为每次强化至少把下面的牌翻一倍,肯定是更优的 然后就只有两种情况 强化牌数量少于 ...
- PKUWC Slay The Spire
题面链接 LOJ sol 好神啊.果然\(dp\)还是做少了,纪录一下现在的思维吧\(QAQ\). 我们首先可以发现期望是骗人的,要不然他乘的是什么xjb玩意. 其实就是要求所有方案的最优方案和. 因 ...
随机推荐
- python2.7升级到python3.6注意事项
python3.6下载地址:https://www.python.org/downloads/source/ 1.安装依赖包:gcc openssl-devel.zlib-devel.readli ...
- 极速Node.js:来自LinkedIn的10个性能提升秘籍
from:http://faylai.iteye.com/blog/1293194 1.避免使用同步的方法 nodejs 是基于单线程.为了让单线程能够处理高并发的请求,我们尽量要避免让线程等待,阻塞 ...
- 导入Frameworks 死活引用不Liao头文件
向工程中拖入或add file时可能会出现Frameworks导入,但是在添加该Frameworks后却引用不到相应的头文件 打开工程文件目录发现frameworks所在的路径并不存在,而是直接在工程 ...
- IBM的SOA方法论之一——五个切入点和八个场景
一.什么是SOA: 面向服务的体系结构(Service-Oriented Architecture,SOA)是一种 IT 体系结构风格,支持将您的业务转换为一组相互链接的服务或可重复业务任务,可在需要 ...
- mongodb简介和特性
1.mongodb是基于文档的(BSON,类似json的键值对来存储),不是基于表格,易于水平扩展,将内部相关的数据放在一起能提高数据库的操作性能.如果你想新建一个新的文档类型,不用事先告诉数据库关于 ...
- 【Tech】单点登录系统CAS服务器端搭建及实现用户名密码由MYSQL数据库验证
CAS是YALE大学发起的一个开源项目,旨在为web应用系统提供一种可靠的单点登录方法.它主要分为client和server端,server端负责对用户的认证工作,client端负责处理对客户端受保护 ...
- 【HackerRank】Bus Station
有n组好朋友在公交车站前排队.第i组有ai个人.还有一辆公交车在路线上行驶.公交车的容量大小为x,即它可以同时运载x个人. 当车站来车时(车总是空载过来),一些组从会队头开始走向公交车. 当然,同一组 ...
- ==、equals与hashCode
== 首先,得说明java数据类型分为基本数据类型和引用数据类型, 基本数据类型有8种: 浮点型:float(4 byte), double(8 byte) 整型:byte(1 byte), sho ...
- Django源码剖析
一.Django底层剖析之一次请求到响应的整个流程 As we all know,所有的Web应用,其本质上其实就是一个socket服务端,而用户的浏览器就是一个socket客户端 #!/usr/bi ...
- 进程控制块PCB结构体 task_struct 描述
进程控制块,英文名(Processing Control Block),简称 PCB . 进程控制块是系统为了管理进程设置的一个专门的数据结构,主要表示进程状态. 每一个进程都对应一个PCB来维护进程 ...