LOJ

BZOJ

洛谷

哪张能力牌能乘攻击啊,太nb了叭


显然如果有能力牌,那么应该选最大的尽可能的打出\(k-1\)张。

然后下面说的期望都是乘总方案数后的,即所有情况的和。然后\(w_i\)统一用\(A_i\)表示了。

\(Solution1\)

所以考虑枚举最终抽到了几张能力牌。那么我们要算:\(F(n,m)\)表示抽到\(n\)张攻击牌,打出最大的\(m\)张的期望伤害;\(G(n,m)\)表示抽到\(n\)张能力牌,打出最大的\(m\)张的期望倍数。

考虑怎么算\(F(n,m)\)。不妨枚举攻击最小的那张是什么。也就是把攻击牌从大到小排序,\(f[i][j]\)表示在前\(i\)张中选\(j\)张的期望伤害,其中第\(i\)张一定取。转移就再枚举一下次小的,\(f[i][j]=C_{i-1}^{j-1}A_i+\sum\limits_{k=j-1}^{i-1}f[k][j-1]\)。

\(G(n,m)\)同理。令\(g[i][j]\)表示从前\(i\)大的能力牌中选\(j\)张的期望倍数,其中第\(i\)张一定取。\(g[i][j]=A_i\sum\limits_{k=j-1}^{i-1}g[k][j-1]\)。

两个DP都可以前缀和优化。所以复杂度是\(O(n^2)\)的。

那么\(F,G\)的转移同样枚举选出来的最小的那张,\(F(n,m)=\sum\limits_{i=m}^{N}C_{N-i}^{n-m}f[i][m]\),\(G(n,m)=\sum\limits_{i=m}^{N}C_{N-i}^{n-m}g[i][m]\)。对于单个\(F/G(n,m)\)的计算是\(O(n)\)的。

然后\(Ans=\sum\limits_{i=1}^{k-1}G(i,i)F(m-i,k-i)+\sum\limits_{i=k}^NG(i,k-1)F(m-i,1)\)。我们只会用到\(O(n)\)个\(F/G\)的值,现算一下即可,总复杂度是\(O(n^2)\)的。

为了方便应该把\(f/g\)的一二维交换下=-=。

\(Solution2\)

设\(f[i][j]\)表示考虑了前\(i\)张牌,抽到了\(j\)张攻击牌的期望伤害。肯定是选出最大的若干张打出。将牌从小到大排序,然后根据\(j\)确定这张牌选不选,有(1年后发现Latex begin{cases}怎么不能用了?凑合看叭...)$$f[i][j]=f[i-1][j]+C_{i-1}^{j-1}A_i+\begin{cases}0,&m-j\geq k-1\ f[i-1][j-1],&m-j<k-1\end{cases}$$

考虑\(i\)的贡献,\(m-j\geq k-1\)时,只能取一张攻击牌,那取\(i\)就能保证打出的是最大的那张;否则取完\(i\)之后还可以在取\(j-1\)张的情况。然后再统计上以前的只考虑\(i-1\)张牌时的\(f[i-1][j]\)(注意这个=-=)。

\(g[i][j]\)表示考虑了前\(i\)张牌,抽到了\(j\)张能力牌的期望倍数。因为是选最大的\(\min(k-1,\ j)\)张打出,所以把能力牌从大到小排序,有$$g[i][j]=g[i-1][j]+\begin{cases}g[i-1][j-1]*A_i,&j<k\ g[i-1][j-1],&j\geq k\end{cases}$$

就是\(j<k\)时用\(A_i\),否则抽到\(A_i\)也不用。

那么答案就是\(\sum_{i=0}^mf[n][i]g[n][m-i]\)啦。

复杂度也是\(O(n^2)\),不过常数要更小。


但是懒得再写代码了,代码是\(Sol1\)的。不然还是有把握搞个BZOJRank1.2的。

//27376kb	9684ms
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <functional>
#define mod 998244353
#define Mod(x) x>=mod&&(x-=mod)
#define Add(x,v) (x+=v)>=mod&&(x-=mod)
#define gc() getchar()
typedef long long LL;
const int N=1505; int A[N],B[N],f[N][N],g[N][N],C[N][N]; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-48,c=gc());
return now;
}
int F(int n,int m,int N)
{
LL ans=0; int *f=::f[m];
for(int i=m; i<=N; ++i) ans+=1ll*C[N-i][n-m]*f[i]%mod;
return ans%mod;
}
int G(int n,int m,int N)
{
LL ans=0; int *g=::g[m];
for(int i=m; i<=N; ++i) ans+=1ll*C[N-i][n-m]*g[i]%mod;
return ans%mod;
} int main()
{
C[0][0]=1;
for(int Ts=read(),mx=0; Ts--; )
{
int n=read(),m=read(),K=read();
if(mx<n)
{
for(int i=mx+1; i<=n; ++i)
{
C[i][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(C[i][j]);
}
mx=n;
}
for(int i=1; i<=n; ++i) A[i]=read();
for(int i=1; i<=n; ++i) B[i]=read();
std::sort(A+1,A+1+n,std::greater<int>()), std::sort(B+1,B+1+n,std::greater<int>()); g[0][0]=1;//!! K=1时会用到啊=-=
for(int i=1; i<=n; ++i) f[1][i]=B[i], g[1][i]=A[i];//or not
for(int i=2,lim=std::min(n,m); i<=lim; ++i)
{
int sf=0,sg=0;
for(int j=i; j<=n; ++j)
Add(sf,f[i-1][j-1]), f[i][j]=(1ll*C[j-1][i-1]*B[j]+sf)%mod,
Add(sg,g[i-1][j-1]), g[i][j]=1ll*A[j]*sg%mod;
}
LL ans=0;
for(int i=std::max(0,m-n); i<=n&&i<=m; ++i)//m-i<=n 枚举的是能力牌 可以是0啊=v=
if(i<K) ans+=1ll*G(i,i,n)*F(m-i,K-i,n)%mod;
else ans+=1ll*G(i,K-1,n)*F(m-i,1,n)%mod;
printf("%lld\n",ans%mod);
} return 0;
}

BZOJ.5467.[PKUWC2018]Slay the Spire(DP)的更多相关文章

  1. LOJ2538 PKUWC2018 Slay the Spire DP

    传送门 不想放题面了,咕咕咕咕咕 这个期望明明是用来吓人的,其实要算的就是所有方案的最多伤害的和. 首先可以知道的是,能出强化牌就出强化牌(当然最后要留一张攻击牌出出去),且数字尽量大 所以说在强化牌 ...

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

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

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

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

  4. [LOJ2538] [PKUWC2018] Slay the Spire

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

  5. [PKUWC2018] Slay the spire

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

  6. 题解-PKUWC2018 Slay the Spire

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

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

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

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

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

  9. BZOJ 5467 Slay the Spire

    BZOJ 5467 Slay the Spire 我的概率基础也太差了.jpg 大概就是这样,因为强化牌至少翻倍,所以打出的牌必定是全部的强化牌或者$k-1$个强化牌,然后剩余的机会打出最大的几个攻击 ...

随机推荐

  1. java基础 关于转换流

    转换流有两种:InputStreamReader:将字节流转换为字符流 OutputStreamWriter:将字符流转换为字节流 什么时候使用转换流?由以下分析: 流对象很多,首先要明确那个流对象. ...

  2. Kindle复活记

    此前,2015年为了配合拆机堂的内容项目,我们将全新Kindle PaperWhite 3进行全球首拆,让网友们第一时间全面了解了Kindle PaperWhite 3的内部构造.但由于进行深度拆解, ...

  3. easyui时间框只选择年月

    html: <input type="text" id="datetime" > js: <script type="text/ja ...

  4. C# - 引用类型

    引用类型(Reference Type) C#是一门使用OOP技术的编程语言(Object Oriented Programming 面向对象编程)面向对象最重要的特性就是接口.继承.多态 C#中所有 ...

  5. Linux 使用 arp-scan 检查是否存在IP地址冲突

    如果前期没有做好IP地址规划,即使有IP地址统一不小心也会犯错!推荐服务器IP地址使用要登记明细,上次机房批量部署服务器,就将已再用的IP又分配给另一台服务器,还好对业务没有造成大的影响. 那么在给服 ...

  6. [Kubernetes]容器日志的收集与管理

    在开始这篇文章之前,首先要明确一点: Kubernetes 中对容器日志的处理方式,都叫做 cluster-level-logging ,也就是说,这个日志处理系统,与容器, Pod 以及 Node ...

  7. 3D Slicer中文教程(七)—图像中值滤波

    1.中值滤波概念 中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制效果好,在抑制随机噪声的同时能有效保护边缘 ...

  8. MSM8909的触摸屏驱动导致的熄屏后重新亮屏速度慢的原因!【转】

    转自:https://blog.csdn.net/kk20000/article/details/83041081 使用的汇顶的触摸驱动的时候会重新亮屏速度慢3秒,而在使用另外一个敦泰触摸驱动的时候没 ...

  9. android app 的插件化、组件化、模块化开发-2

    Android 插件化 ——指将一个程序划分为不同的部分,比如一般 App的皮肤样式就可以看成一个插件 Android 组件化 ——这个概念实际跟上面相差不那么明显,组件和插件较大的区别就是:组件是指 ...

  10. [原创]Modelsim后仿真

    因调试需要,进行后仿真,ISE生成的sim文件和sdf文件 `timescale ns/ ps module lut_dly ( clkout, fpga_clk, config_in ); outp ...