传送门

不想放题面了,咕咕咕咕咕


这个期望明明是用来吓人的,其实要算的就是所有方案的最多伤害的和。

首先可以知道的是,能出强化牌就出强化牌(当然最后要留一张攻击牌出出去),且数字尽量大

所以说在强化牌数量$< K$时会打出所有强化牌和剩下的最大的攻击牌,而强化牌数量$\geq K$的时候则会打出$K-1$张强化牌和$1$张攻击牌,且它们的数字都是最大的

我们不妨计算每一种最优打出的方案存在在多少种抽取方案中。

设$f_{i,j}$表示使用$i$张强化牌,其中数值最小的牌是第$j$张时的方案的强化数值之和,$g_{i,j}$表示使用$i$张攻击牌,其中数值最小的牌是第$j$张时的方案的攻击数值之和,简单的前缀和优化DP就可以完成。处理完之后,所有抽取了$x$张强化牌和$y$张攻击牌,选择$i$张强化牌和$j$张攻击牌的方案的总伤害和就是

$$\sum\limits_k \sum\limits_l f_{i,k} \times g_{j,l} \times C_{k-1}^{x-i} \times C_{l-1}^{y-j}$$

两个理解:

①$f$和$g$中间用乘号是因为$f$中间的每一个方案和$g$中的每一个方案都可以对应产生一种抽取方式

②后面的两个组合数的意思是:对于强化牌,已经使用了$i$张,最小的是$k$,那么剩下的$x-i$张需要在剩余的$k-1$中抽取,方案数就是组合数,后面同理

那么我们枚举强化牌抽了多少张,就可以直接计算答案。

 #include<bits/stdc++.h>
//This code is written by Itst
using namespace std; inline int read(){
int a = ;
bool f = ;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ '');
c = getchar();
}
return f ? -a : a;
} const int MOD = , MAXN = ;
long long dp[MAXN + ][MAXN + ] , f[MAXN + ][MAXN + ] , g[MAXN + ][MAXN + ] , num[][MAXN + ] , jc[MAXN + ] , ny[MAXN + ] , N , M , K , ans; bool cmp(int a , int b){
return a > b;
} inline int poww(long long a , int b){
int times = ;
while(b){
if(b & )
times = times * a % MOD;
a = a * a % MOD;
b >>= ;
}
return times;
} signed main(){
#ifndef ONLINE_JUDGE
freopen("2538.in" , "r" , stdin);
//freopen("2538.out" , "w" , stdout);
#endif
jc[] = ;
for(long long i = ; i <= MAXN ; ++i)
jc[i] = jc[i - ] * i % MOD;
ny[MAXN] = poww(jc[MAXN] , MOD - );
for(long long i = MAXN - ; i >= ; --i)
ny[i] = ny[i + ] * (i + ) % MOD;
for(int i = ; i <= MAXN ; ++i)
dp[][i] = ;
for(int i = ; i <= MAXN ; ++i)
for(int j = ; j <= MAXN ; ++j)
dp[i][j] = (dp[i - ][j - ] + dp[i][j - ]) % MOD;
for(int i = ; i <= MAXN ; ++i)
f[][i] = ; for(int T = read() ; T ; --T){
N = read();
M = read();
K = read();
for(int i = ; i <= N ; ++i)
num[][i] = read();
sort(num[] + , num[] + N + , cmp);
for(int i = ; i <= N ; ++i)
num[][i] = read();
sort(num[] + , num[] + N + , cmp);
ans = ; for(int i = ; i <= N ; ++i)
for(int j = ; j <= N ; ++j){
f[i][j] = (1ll * f[i - ][j - ] * num[][j] + f[i][j - ]) % MOD;
g[i][j] = (g[i - ][j - ] + 1ll * (dp[i][j] - dp[i][j - ] + MOD) * num[][j] + g[i][j - ]) % MOD;
} for(int i = ; i < K ; ++i){
int sum1 = f[i][N] , sum2 = ;
for(int j = K - i ; N - j >= M - K ; ++j)
sum2 = (sum2 + 1ll * (g[K - i][j] - g[K - i][j - ] + MOD) * jc[N - j] % MOD * ny[M - K] % MOD * ny[N - j - (M - K)]) % MOD;
ans = (ans + 1ll * sum1 * sum2) % MOD;
} for(int i = K ; i < M ; ++i){
int sum1 = , sum2 = ;
for(int j = K - ; N - j >= i - (K - ) ; ++j)
sum1 = (sum1 + 1ll * (f[K - ][j] - f[K - ][j - ] + MOD) * jc[N - j] % MOD * ny[i - (K - )] % MOD * ny[N - j - (i - (K - ))]) % MOD;
for(int j = ; N - j >= M - i - ; ++j)
sum2 = (sum2 + 1ll * (g[][j] - g[][j - ] + MOD) * jc[N - j] % MOD * ny[M - i - ] % MOD * ny[N - j - (M - i - )]) % MOD;
ans = (ans + 1ll * sum1 * sum2) % MOD;
}
cout << ans << endl;
}
return ;
}

LOJ2538 PKUWC2018 Slay the Spire DP的更多相关文章

  1. [LOJ2538][PKUWC2018]Slay the Spire:DP

    分析 学会新姿势!我们可以通过调整DP顺序来体现选取物品的优先顺序! 显然选取强化牌的最优策略是倍数从高到低,能选就选,最多选\(k-1\)张,选取攻击牌的最优策略是伤害从高到低,尽量少选,但最少选\ ...

  2. BZOJ.5467.[PKUWC2018]Slay the Spire(DP)

    LOJ BZOJ 洛谷 哪张能力牌能乘攻击啊,太nb了叭 显然如果有能力牌,那么应该选最大的尽可能的打出\(k-1\)张. 然后下面说的期望都是乘总方案数后的,即所有情况的和.然后\(w_i\)统一用 ...

  3. [LOJ2538] [PKUWC2018] Slay the Spire

    题目链接 LOJ:https://loj.ac/problem/2538 Solution 计数好题. 首先可以发现这题和期望没关系. 其次对于手上的一套牌,设我们有\(a\)张强化牌,那么: 如果\ ...

  4. 洛谷 P5299 - [PKUWC2018]Slay the Spire(组合数学+dp)

    题面传送门 hot tea 啊--这种风格及难度的题放在省选 D2T1 左右还是挺喜闻乐见的罢 首先考虑对于固定的 \(m\) 张牌怎样求出最优的打牌策略,假设我们抽到了 \(p\) 张强化牌,攻击力 ...

  5. 【loj2538】 【PKUWC 2018】Slay the Spire dp

    我们不难发现,假设抽了x张攻击牌,y张强化牌,那么肯定是打出尽可能多张的强化牌后,再开始出攻击牌(当然最少要一张攻击牌) 我们设G(i,j)表示:所有(抽到的攻击牌牌数为i,打出的攻击牌牌数为j)的方 ...

  6. 题解-PKUWC2018 Slay the Spire

    Problem loj2538 Solution 在考场上当然要学会写暴力,考虑如果手上已经有了\(a\)张攻击牌和\(b\)张强化牌: 首先强化牌会在攻击牌之前用(废话),其次要将两种牌分别从大往小 ...

  7. [PKUWC2018] Slay the spire

    Description 现在有 \(n\) 张强化牌和 \(n\) 张攻击牌: 攻击牌:打出后对对方造成等于牌上的数字的伤害. 强化牌:打出后,假设该强化牌上的数字为 \(x\),则其他剩下的攻击牌的 ...

  8. 【洛谷5299】[PKUWC2018] Slay the Spire(组合数学)

    点此看题面 大致题意: 有\(n\)张强化牌\(a_i\)和\(n\)张攻击牌\(b_i\),每张牌有一个权值(强化牌的权值大于\(1\)),每张强化牌能使所有攻击牌的权值乘上这张强化牌的权值,每张攻 ...

  9. LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)

    Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...

随机推荐

  1. 【读书笔记】iOS-iOS开发之iOS程序偏好设置(Settings Bundle)的使用

    在Android手机上, 在某个程序里,通过按Menu键,一般都会打开这个程序的设置,而在iOS里,系统提供了一个很好的保存程序设置的机制.就是使用Settings Bundle. 在按了HOME键的 ...

  2. 如何判断一个 APP页面是否是H5页面

    1.无网络断开网络,显示404或则错误页面的是H5 2.页面布局a.在手机设置.开发者选项中开启显示布局边界功能:b.进入应用查看布局边界:c.原生应用可以看到各个控件的布局边界,H5只有整个页面的一 ...

  3. mysql 优化配置参数(my.cnf)

    max_connections:允许客户端并发连接的最大数量,默认值是151,一般将该参数设置为500-2000max_connect_errors:如果客户端尝试连接的错误数量超过这个参数设置的值, ...

  4. Android开发专业名词及工具概述

    前言: 系统的学习下Android开发中涉及到的一些专业名词 和Android开发工具 名词: 一.SDK(Software Development Kit) 软件开发工具包:一般都是一些软件工程师为 ...

  5. Angular2 富文本编辑器 ng2-ckeditor 的使用

    本文介绍如何在 Angular 中使用 ng2-ckeditor 控件,示例代码基于 angular 6.0.2,node 8.11.2,  ng2-ckeditor 4.9.2 环境   1. 安装 ...

  6. 原来这样就可以开发出一个百万量级的Android相机

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由QQ空间开发团队发表于云+社区专栏 最近我负责开发了一个跟Android相机有关的需求,新功能允许用户使用手机摄像头,快速拍摄特定尺寸 ...

  7. Session Cookies随笔

    1.对于Session而言 它是用来保存在服务端的信息,可以用来做登录验证,在后台保存有用信息. 一个浏览器访问一个网站,就是建立一个连接,连接信息是独立的,就是在该建立的连接内,保存到Session ...

  8. 9.4、__del__、__doc__、__dict__、__module__、__getitem__、__setitem__、__delitem__、__str__、__repr__、__call__

    相关内容: __del__.__doc__.__dict__.__module__.__getitem__.__setitem__.__delitem__.__str__.__repr__.__cal ...

  9. Dbvisualizer软件设置SQL语句的自动提示功能

    之前从来没有使用过Dbvisualizer软件,用起来之后发现比mysqlfront不是好一点.之前一直不知道sql语句的自动提示功能,只能一个个单词输入,而且不是默认设置.之后在网上找到了怎么设置, ...

  10. iptable用法

    一:添加屏蔽IP #禁止此IP访问服务器iptables -I INPUT -s 1.2.3.4 -j DROP或iptables -A INPUT -s 1.2.3.4 -j DROP#禁止服务器访 ...