即求所有情况的最大伤害之和。容易发现应该先打强化牌,至少打一张攻击牌。同样显然的是强化牌和攻击牌都应该按从大到小的顺序打。进一步可以发现,只要还有强化牌,就应该使用(当然至少留一次攻击的机会)。

  于是将强化牌和攻击牌各自从大到小排序。显然可以将其分开考虑。对强化牌,设f[i][j]为前i张牌抽到j张并打出的强化倍数之和,则显然有f[i][j]=f[i-1][j]+f[i-1][j-1]·w[i]。这样就搞定了强化牌可以打完的情况。同时设g[i]为抽i张打出k-1张的强化倍数之和,dp过程中通过f数组计算,注意避免重复。对于攻击牌也进行类似dp。然后枚举两种牌各抽了几张合并一下答案即可。注意细节。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 3010
#define P 998244353
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int T,n,m,k,a[N],b[N],f[][N][N],g[][N],C[N][N],h[N];
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5467.in","r",stdin);
freopen("bzoj5467.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
T=read();
while (T--)
{
n=read(),m=read(),k=read();int lim=min(k-,n);
C[][]=;
for (int i=;i<=n;i++)
{
C[i][]=C[i][i]=;
for (int j=;j<n;j++)
C[i][j]=(C[i-][j-]+C[i-][j])%P;
}
memset(f,,sizeof(f));memset(g,,sizeof(g));memset(h,,sizeof(h));
for (int i=;i<=n;i++) a[i]=read();
for (int i=;i<=n;i++) b[i]=read();
sort(a+,a+n+),reverse(a+,a+n+);
sort(b+,b+n+),reverse(b+,b+n+);
f[][][]=;
for (int i=;i<=n;i++)
{
f[][i][]=;
for (int j=;j<=lim;j++)
f[][i][j]=(f[][i-][j]+1ll*f[][i-][j-]*a[i])%P;
if (lim==) for (int j=;j<=n;j++) g[][j]=C[n][j];
else
for (int j=lim;j<=n;j++)
g[][j]=(g[][j]+1ll*f[][i-][lim-]*a[i]%P*C[n-i][j-lim])%P;
}
for (int i=;i<=n;i++)
{
for (int j=;j<=m;j++)
f[][i][j]=(f[][i-][j]+f[][i-][j-]+1ll*b[i]*C[i-][j-])%P;
for (int j=m-k+;j<=n;j++)
g[][j]=(g[][j]+(f[][i-][j-(m-k)-]+1ll*b[i]*C[i-][j-(m-k)-])%P*C[n-i][m-k])%P;
}
for (int i=;i<=min(n,m);i++)
for (int j=;j<=n;j++)
h[i]=(h[i]+1ll*b[j]*C[n-j][i-])%P;
/*for (int i=0;i<=n;i++) cout<<f[0][n][i]<<' ';cout<<endl;
for (int i=0;i<=n;i++) cout<<g[0][i]<<' ';cout<<endl;
for (int i=0;i<=n;i++) cout<<f[1][n][i]<<' ';cout<<endl;
for (int i=0;i<=n;i++) cout<<g[1][i]<<' ';cout<<endl;
for (int i=0;i<=n;i++) cout<<h[i]<<' ';cout<<endl;*/
int ans=;
for (int i=max(,m-n);i<=min(n,m);i++)
if (i<=lim) ans=(ans+1ll*f[][n][i]*g[][m-i])%P;//抽了i张强化牌 全部出完 剩余m-i张攻击牌 选m-k张不出
else ans=(ans+1ll*g[][i]*h[m-i])%P;//抽了i张强化牌 选lim张出 剩余m-i张攻击牌 出1张
printf("%d\n",ans);
}
return ;
}

BZOJ5467 PKUWC2018Slay the Spire(动态规划)的更多相关文章

  1. [.NET] 打造一个很简单的文档转换器 - 使用组件 Spire.Office

    打造一个很简单的文档转换器 - 使用组件 Spire.Office [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6024827.html 序 之前,& ...

  2. 高效而稳定的企业级.NET Office 组件Spire(.NET组件介绍之二)

    在项目开发中,尤其是企业的业务系统中,对文档的操作是非常多的,有时几乎给人一种错觉的是”这个系统似乎就是专门操作文档的“.毕竟现在的很多办公中大都是在PC端操作文档等软件,在这些庞大而繁重的业务中,单 ...

  3. [.NET] 开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc

    开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc [博主]反骨仔 [原文地址]http://www.cnblogs.com/li ...

  4. 增强学习(三)----- MDP的动态规划解法

    上一篇我们已经说到了,增强学习的目的就是求解马尔可夫决策过程(MDP)的最优策略,使其在任意初始状态下,都能获得最大的Vπ值.(本文不考虑非马尔可夫环境和不完全可观测马尔可夫决策过程(POMDP)中的 ...

  5. 简单动态规划-LeetCode198

    题目:House Robber You are a professional robber planning to rob houses along a street. Each house has ...

  6. C#组件系列——又一款Excel处理神器Spire.XLS,你值得拥有(二)

    前言:上篇 C#组件系列——又一款Excel处理神器Spire.XLS,你值得拥有 介绍了下组件的两个功能,说不上特色,但确实能解决我们项目中的一些实际问题,这两天继续研究了下这个组件,觉得有些功能用 ...

  7. C#组件系列——又一款Excel处理神器Spire.XLS,你值得拥有

    前言:最近项目里面有一些对Excel操作的需求,博主想都没想,NPOI呗,简单.开源.免费,大家都喜欢!确实,对于一些简单的Excel导入.导出.合并单元格等,它都没啥太大的问题,但是这次的需求有两点 ...

  8. 动态规划 Dynamic Programming

    March 26, 2013 作者:Hawstein 出处:http://hawstein.com/posts/dp-novice-to-advanced.html 声明:本文采用以下协议进行授权: ...

  9. 动态规划之最长公共子序列(LCS)

    转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...

随机推荐

  1. rpm yum apt-get redhat centos ubuntu

    rpm是由红帽公司开发的软件包管理方式,使用rpm我们可以方便的进行软件的安装.查询.卸载.升级等工作.但是rpm软件包之间的依赖性问题往往会很繁琐,尤其是软件由多个rpm包组成时.Yum(全称为 Y ...

  2. 第17章 EXTI—外部中断/事件控制器

    第17章     EXTI—外部中断/事件控制器 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...

  3. sql语句之表间字段值复制遇到的一些问题--基于mysql

    好久没来园子了,转眼2017已经到3月份了,前段时间一直忙没时间写博客(其实是自己懒),感觉内心好惭愧.昨天临下班前,技术老大突然对我说要改下表结构,问我能不能实现将一个表的字段值复制到另外一个表的某 ...

  4. 20155334 网络对抗PC平台逆向破解(二)

    注入Shellcode并运行攻击 shellcode就是一段机器指令(code) 通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe) ...

  5. Spring+SpringMVC+MyBatis+easyUI整合优化篇(一)Java语言中System.out.print与Log的比较

    作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 前言 距离上一次更新博客有一段时间了,主要是因为最近有开发任务,另外 ...

  6. 【技巧】如何清空SQLServer的日志文件

    一.应用场景 在一次项目实施的过程中,发现一个小问题,在开发环境中备份下来的数据库大约15G,压缩后更小一些,但是在另外一台设备上部署的时候,发现总是提示空间不足.通过查询发现数据库的日志文件比较大, ...

  7. 杂谈---这些大忌,你在面试的时候发生过吗?(NO.1)

              面试是大部分人的人生当中难免会遇到的一件事,那么具体在面试当中有哪些忌讳呢? 说到面试,在这里尤其特指技术岗位的面试,很多时候,结果并不仅仅取决于你的技术广度与深度,亦或是你的笔试 ...

  8. 一篇带你读懂TCP之“滑动窗口”协议

    前言 你现在的努力,是为了以后有更多的选择. 在上一篇文章通过"表白"方式,让我们快速了解网络七层协议了解了网络七层协议. 接下来我们要把重心放在网络传输的可靠性上面.一起来看TC ...

  9. PAT甲题题解-1064. Complete Binary Search Tree (30)-中序和层次遍历,水

    由于是满二叉树,用数组既可以表示父节点是i,则左孩子是2*i,右孩子是2*i+1另外根据二分搜索树的性质,中序遍历恰好是从小到大排序因此先中序遍历填充节点对应的值,然后再层次遍历输出即可. 又是一道遍 ...

  10. Linux内核分析——第二章 从内核出发

    第二章 从内核出发 一.获取内核源码 1.Git是分布式的:下载和管理Linux内核源代码: 2.获取最新提交到版本树的一个副本 $ git clone git://git.kernel.org/pu ...