BZOJ 5467 Slay the Spire
BZOJ 5467 Slay the Spire
- 我的概率基础也太差了.jpg
大概就是这样,因为强化牌至少翻倍,所以打出的牌必定是全部的强化牌或者$k-1$个强化牌,然后剩余的机会打出最大的几个攻击牌。
我们对于强化牌和攻击牌分别做,并且显然,排序并不会影响答案。
$f[i][j]$表示前$i$张牌,取到$j$张,第$i$张必定取的最大强化值之积,$g[i][j]$表示前$i$张攻击牌,取到$j$张,第$i$张必定取的最大伤害和。(一般来说,应该先考虑第$i$张不必需取的最大值,但是由于那样设计状态并不能优化成$n^2$,所以只能选择第$i$张必须选的答案)
$f[i][j]=a_i\times \sum\limits_{k=j-1}^{i-1} f[k][j-1]$
$g[i][j]=C(i-1,j-1)\times b_i+\sum\limits_{k=j-1}^{i-1} g[k][j-1]$
然后剩下的就是如何计算答案了。
那么很显然,我们要求的是前$n$张排中,选择$j$个,第$n$个不必需选择的答案。
因此设$F(i,j)$表示摸到$i$张,选择$j$个的最大强化之积。那么很显然,$F(i,j)=\sum\limits_{k=i}^nf[k][j]\times C(n-k,i-j)$
同时设$G(i,j)$表示摸到$i$张,选择$j$个的最大伤害之和。那么很显然,$G(i,j)=\sum\limits_{k=i}^n g[k][j]\times C(n-k,i-j)$
同样,根据我们最初得到的结论,$ans=\sum\limits_{i=0}^{k-1}F(i,i)\times G(m-i,k-i)+\sum\limits_{i=k}^m F(i,k-1)\times G(m-i,1)$
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
using namespace std;
#define N 3005
#define ll long long
#define mod 998244353
int f[N][N],g[N][N],n,k,a[N],b[N],m,sum[N],C[N][N];
void init()
{
for(int i=0;i<=3000;i++)
{
C[i][0]=1;
for(int j=1;j<=i;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
int F(int x,int y)
{
if(x<y)return 0;if(!y)return C[n][x];int ret=0;
for(int i=x-y+1;i<=n-y+1;i++)ret=(ret+(ll)f[y][i]*C[i-1][x-y])%mod;
return ret;
}
int G(int x,int y)
{
if(x<y)return 0;int ret=0;
for(int i=x-y+1;i<=n-y+1;i++)ret=(ret+(ll)g[y][i]*C[i-1][x-y])%mod;
return ret;
}
void solve()
{
scanf("%d%d%d",&n,&m,&k);
// memset(f,0,sizeof(f));memset(g,0,sizeof(g));
for(int i=1;i<=n;i++)
for(int j=1;j<=n-i+1;j++)
f[i][j]=g[i][j]=0;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)scanf("%d",&b[i]);
sort(a+1,a+n+1);sort(b+1,b+n+1);
for(int i=1;i<=n;i++)f[1][i]=a[i],sum[i]=(sum[i-1]+a[i])%mod;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=n-i+1;j++)f[i][j]=(ll)a[j]*(sum[n]-sum[j]+mod)%mod;
for(int j=1;j<=n-i+1;j++)sum[j]=(sum[j-1]+f[i][j])%mod;
for(int j=n-i+2;j<=n;j++)sum[j]=sum[j-1];
}
for(int i=1;i<=n;i++)g[1][i]=b[i],sum[i]=(sum[i-1]+b[i])%mod;
for(int i=2;i<=n;i++)
{
for(int j=1;j<=n-i+1;j++)g[i][j]=((ll)b[j]*C[n-j][i-1]+sum[n]-sum[j]+mod)%mod;
for(int j=1;j<=n-i+1;j++)sum[j]=(sum[j-1]+g[i][j])%mod;
for(int j=n-i+2;j<=n;j++)sum[j]=sum[j-1];
}
int ans=0;
for(int i=0;i<m;i++)
{
if(i<k)ans=(ans+(ll)F(i,i)*G(m-i,k-i))%mod;
else ans=(ans+(ll)F(i,k-1)*G(m-i,1))%mod;
}
printf("%d\n",ans);
}
int main(){init();int T;scanf("%d",&T);while(T--)solve();return 0;}
BZOJ 5467 Slay the Spire的更多相关文章
- 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玩意. 其实就是要求所有方案的最优方案和. 因 ...
- loj2538 「PKUWC2018」Slay the Spire 【dp】
题目链接 loj2538 题解 比较明显的是,由于强化牌倍数大于\(1\),肯定是能用强化牌尽量用强化牌 如果强化牌大于等于\(k\),就留一个位给攻击牌 所以我们将两种牌分别排序,企图计算\(F(i ...
随机推荐
- 判断字符串a和b是否互为旋转词
旋转词:把字符串str的任意部分移动到后面形成的新字符串叫做字符串str的旋转词. 比如abc的旋转词有 abc,acb,cba,... 判断str1和str2是否互为旋转词,其最优解可以是时间复杂度 ...
- ALTER SYSTEM ARCHIVELOG CURRENT挂起案例
最近两天,一台ORACLE数据库的作业执行delete_ob_get_epps.sh脚本清理过期备份时,执行下面SQL语句就会被阻塞,在监控工具DPA里面部分截图如下(图片分开截断) sql 'alt ...
- 洗礼灵魂,修炼python(64)--爬虫篇—re模块/正则表达式(2)
前面学习了元家军以及其他的字符匹配方法,那得会用啊对吧?本篇博文就简单的解析怎么运用 正则表达式使用 前面说了正则表达式的知识点,本篇博文就是针对常用的正则表达式进行举例解析.相信你知道要用正则表达式 ...
- C#中ExecuteReader、ExecuteNonQuery、ExecuteScalar、SqlDataReader、SqlDataAdapter应该怎么用?
C#中ExecuteReader.ExecuteNonQuery.ExecuteScalar.SqlDataReader.SqlDataAdapter应该怎么用? (2013-10-16 13:21: ...
- Django之--MVC的Model
在上一篇:Django之--通过MVC架构的html模板展示Hello World! 讲述了基本的MVC模型,但是却并没有测试Model的作用,本文通过mysql数据库来测试. Django自带的mo ...
- SQLSERVER查询数据库死锁的存储过程
USE [IdentityDemo] GO /****** Object: StoredProcedure [dbo].[sp_who_lock] Script Date: 2019/1/17 10: ...
- Linux进程调度器概述--Linux进程的管理与调度(十五)
调度器面对的情形就是这样, 其任务是在程序之间共享CPU时间, 创造并行执行的错觉, 该任务分为两个不同的部分, 其中一个涉及调度策略, 另外一个涉及上下文切换. 1 背景知识 1.1 什么是调度器 ...
- LeetCode算法题-First Unique Character in a String(Java实现)
这是悦乐书的第213次更新,第226篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第81题(顺位题号是387).给定一个字符串,找到它中的第一个非重复字符并返回它的索引. ...
- InfluxDB基本概念和操作
InfluxDB基本概念 1.数据格式 在 InfluxDB 中,我们可以粗略的将要存入的一条数据看作一个虚拟的 key 和其对应的 value(field value).格式如下: 1 cpu_us ...
- java访问mysql数据库
package com.mysql.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.R ...