【loj2538】 【PKUWC 2018】Slay the Spire dp
我们不难发现,假设抽了x张攻击牌,y张强化牌,那么肯定是打出尽可能多张的强化牌后,再开始出攻击牌(当然最少要一张攻击牌)
我们设G(i,j)表示:所有(抽到的攻击牌牌数为i,打出的攻击牌牌数为j)的方案,所产生的攻击值的总和
形式化地说:$G(i,j)=\sum\limits_{S∈攻击牌\and|S|=i}S中前j大的牌的攻击值之和$
考虑到G(i,j)难以一次求出,我们考虑设置一些中间变量
设g[i][j]表示:我们对攻击牌从小大大进行排序,目前选了i张牌,其中最小的牌是第j张的总贡献,其中b[j]表示第j小的牌的攻击值
当i=1时,有$g[i][j]=b[j]$
当i>1时,有$g[i][j]=b[j]\times \binom{n-j+1}{i}+\sum\limits_{k=j+1}^{n} g[i-1][k]$
后面那个$\sum$我们可以通过求前缀和,实现快速求解
考虑如何通过g(i,j)求解G(i,j)
不难推出:$G(i,j)=\sum\limits_{k=1}^{n-j+1} g[i][k]$
我们设F(i,j)表示:所有(抽到的强化牌牌数为i,打出的强化牌数为j)的方案里,每一个方案所产生的贡献(抽到的i张牌中,最大的j张牌之积)的和
形式化地说:$F(i,j)=\sum\limits_{S∈强化牌\and|S|=i}S中前j大的牌的强化值之积$
考虑到F(i,j)难以一次求出,我们考虑设置一些中间变量
设f[i][j]表示:我们对强化牌从小大大进行排序,目前选了i张牌,其中最小的牌是第j张的总贡献,其中a[j]表示第j小的牌的攻击值
当i=1时,有$f[i][j]=a[j]$
当i>1时,有$f[i][j]=a[j]\times \sum\limits_{k=j+1}^{n} f[i-1][k]$
后面那个$\sum$我们可以通过求前缀和,实现快速求解
考虑如何通过f(i,j)求解F(i,j)
不难推出:$F(i,j)=\sum\limits_{k=1}^{n-j+1} f[i][k]$
最后我们要求的答案ans,假设当前,我们抽到的强化牌数量为i
若i<k,则$ans+=F(i,i)\times G(m-i,k-i)$
若i≥k,则$ans+=F(i,k-1)\times G(m-i,1)$
完结撒花~
1 #include <algorithm>
2 #include <iostream>
3 #include <cstring>
4 #include <cstdio>
5 using namespace std;
6 typedef long long ll;
7 const int mod=998244353;
8 int T, n, m, k, a[1505], b[1505], c[3005][3005], f[1505][1505];
9 int g[1505][1505], sum[1505];
10 int F(int x, int y){
11 if(x<y) return 0;
12 if(!y) return c[n][x];
13 int re=0;
14 for(int j=x-y+1; j<=n-y+1; j++)
15 re = (re + (ll)f[y][j]*c[j-1][x-y]%mod) % mod;
16 //感性理解一下……大概就是把x-y张不打出的牌放到j前头,这里我讲不太清QAQ
17 return re;
18 }
19 int G(int x, int y){
20 if(x<y) return 0;
21 int re=0;
22 for(int j=x-y+1; j<=n-y+1; j++)
23 re = (re + (ll)g[y][j]*c[j-1][x-y]%mod) % mod;
24 return re;
25 }
26 int main(){
27 cin>>T;
28 for(int i=0; i<=3000; i++){
29 c[i][0] = 1;
30 for(int j=1; j<=i; j++)
31 c[i][j] = (c[i-1][j-1] + c[i-1][j]) % mod;
32 }
33 while(T--){
34 memset(f, 0, sizeof(f));
35 memset(g, 0, sizeof(g));
36 scanf("%d %d %d", &n, &m, &k);
37 for(int i=1; i<=n; i++) scanf("%d", &a[i]);
38 for(int i=1; i<=n; i++) scanf("%d", &b[i]);
39 sort(a+1, a+1+n);//跟牌的顺序无关,可以sort
40 sort(b+1, b+1+n);
41 for(int i=1; i<=n; i++){
42 f[1][i] = a[i];//初始化f[][],显然只选1张的倍率之和是a[i]
43 sum[i] = (sum[i-1] + a[i]) % mod;//前缀和,方便转移
44 }
45 for(int i=2; i<=n; i++){
46 for(int j=1; j<=n-i+1; j++)
47 f[i][j] = (ll)a[j] * (sum[n]-sum[j]+mod) % mod;
48 //打了i张牌,最前头的是第j张,那它就是f[i-1][j+1..n]的和再乘上第j号元素。这个转移的思想是枚举在打了i-1张牌的时候最前头的是哪一张
49 for(int j=1; j<=n; j++)
50 sum[j] = (sum[j-1] + f[i][j]) % mod;
51 }
52 for(int i=1; i<=n; i++){
53 g[1][i] = b[i];
54 sum[i] = (sum[i-1] + b[i]) % mod;
55 }
56 for(int i=2; i<=n; i++){
57 for(int j=1; j<=n-i+1; j++)
58 g[i][j] = ((ll)b[j]*c[n-j][i-1]%mod+(sum[n]-sum[j]+mod)%mod) % mod;
59 //打了i张牌,最前头的是第j张。注意g代表的是(不加强化的)攻击力和。在这种情况下,打了i-1张牌的总情况是c[n-j][i-1]种(j+1..n中选i-1个的方案数),这是第一项;第二项就是继承自g[i-1][j+1..n]
60 for(int j=1; j<=n; j++)
61 sum[j] = (sum[j-1] + g[i][j]) % mod;
62 }
63 int ans=0;
64 for(int i=0; i<m; i++)
65 if(i<k) ans = (ans + (ll)F(i,i)*G(m-i,k-i)%mod) % mod;
66 else ans = (ans + (ll)F(i,k-1)*G(m-i,1)%mod) % mod;
67 printf("%d\n", ans);
68 }
69 return 0;
70 }
【loj2538】 【PKUWC 2018】Slay the Spire dp的更多相关文章
- LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)
Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...
- loj2538 「PKUWC 2018」Slay the Spire
pkusc 快到了--做点题涨涨 rp. ref我好菜啊QAQ. 可以发现期望只是一个幌子.我们的目的是:对于所有随机的选择方法(一共 \(\binom{2n}{m}\)种),这些选择方法都最优地打出 ...
- 【BZOJ5251】【八省联考2018】劈配(网络流,二分答案)
[BZOJ5251][八省联考2018]劈配(网络流,二分答案) 题面 洛谷 BZOJ Description 一年一度的综艺节目<中国新代码>又开始了. Zayid从小就梦想成为一名程序 ...
- 【BZOJ5248】【九省联考2018】一双木棋(搜索,哈希)
[BZOJ5248][九省联考2018]一双木棋(搜索,哈希) 题面 BZOJ Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何 ...
- LOJ #2540. 「PKUWC 2018」随机算法(概率dp)
题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...
- 【LOJ2542】【PKUWC 2018】随机游走 min-max容斥 树上高斯消元
题目描述 有一棵 \(n\) 个点的树.你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(q\) 次询问,每次询问给定一个集合 \(S\),求如果从 \(x\) 出发一 ...
- 【Asia Yokohama Regional Contest 2018】Arithmetic Progressions
题目大意:给定 N(1<N<=5000) 个不同元素组成的集合,求从中选出若干数字组成的等差数列最长是多少. 题解:直接暴力有 \(O(n^3)\) 的算法,即:枚举等差数列的前两个值,再 ...
- 【LOJ】#2538. 「PKUWC2018」Slay the Spire
题解 由于强化卡都是大于1的,我们分析一下就会发现,尽可能多的用强化卡,至少用一张攻击卡,一定是每组卡牌的最优选择 所以我们把攻击卡和强化卡从大到小排序 我们设\(g[i][j]\)表示前i张卡牌里选 ...
- LOJ2538 PKUWC2018 Slay the Spire DP
传送门 不想放题面了,咕咕咕咕咕 这个期望明明是用来吓人的,其实要算的就是所有方案的最多伤害的和. 首先可以知道的是,能出强化牌就出强化牌(当然最后要留一张攻击牌出出去),且数字尽量大 所以说在强化牌 ...
随机推荐
- GaussDB(for MySQL) :Partial Result Cache,通过缓存中间结果对算子进行加速
摘要:华为云数据库高级内核技术专家详解GaussDB(for MySQL)Partial Result Cache特性,如何通过缓存中间结果对算子进行加速? 本文分享自华为云社区<GaussDB ...
- NC50038 kotori和糖果
NC50038 kotori和糖果 题目 题目描述 kotori共有 \(n\) 块糖果,每块糖果的初始状态是分散的,她想把这些糖果聚在一堆.但她每次只能把两堆糖果合并成一堆. 已知把两堆数量为 \( ...
- python虚拟环境(python+conda)
python的不同虚拟环境就相当于在电脑上装了很多个python.下面写python创建虚拟环境.conda创建虚拟环境和在pycharm中配置一下. python -m venv (要创虚拟环境的路 ...
- java 九九乘法表(for循环)
package study5ran2yl.study; public class ForDemo01 { public static void main(String[] args) { int h; ...
- NC20566 [SCOI2010]游戏
题目链接 题目 题目描述 lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属 ...
- Solution -「CF520E」Pluses everywhere
Step 1. 转化一步题目:考虑有 \(n\) 个小球,每个小球有 \(a_i\) 的价值,\(m\) 个板子,把板子插进小球间的空隙,且不能插在第 \(1\) 个球之前与第 \(n\) 个球之后. ...
- NOI / 2.1基本算法之枚举2673:比赛排名
总时间限制: 1000ms 内存限制: 65536kB 描述 5名运动员参加100米赛跑,各自对比赛结果进行了预测: A说:E是第1名. B说:我是第2名. C说:A肯定垫底. D说:C肯定拿不了第1 ...
- react 吸顶实现
今天获取到一个需求,其实就是吸顶的需求,页面下滑,某一块dom隐藏时发生吸顶现象.这种特效其实老生常谈了,但是在这次做的时候,突发奇想,能否将其做成一个 hook ,从而实现出传递ref即可使得 do ...
- Swift高仿iOS网易云音乐Moya+RxSwift+Kingfisher+MVC+MVVM
效果 列文章目录 因为目录比较多,每次更新这里比较麻烦,所以推荐点击到主页,然后查看iOS Swift云音乐专栏. 目简介 这是一个使用Swift(还有OC版本)语言,从0开发一个iOS平台,接近企业 ...
- Linux入门操作介绍
Linux 是由unix衍生而来(小知识:mac也是使用unix核心),由全世界的程序员一起开发的开源系统.如今基于linux已经有了很多版本,我们后面使用的就是衍生版本之一的Ubuntu. Ubun ...