PKUSC2018 Slay The Spire

2024-01-24 10:50
文章标签 spire slay pkusc2018

本文主要是介绍PKUSC2018 Slay The Spire,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

有攻击牌和强化牌各 $n$ 张,强化牌可以让之后所有攻击牌攻击力乘一个大于 $1$ 的系数,攻击牌可以造成伤害

求所有“抽出 $m$ 张然后打 $k$ 张”能造成的伤害之和

$k,m,2n \leq 3000$

sol:

冷静一下,发现强化牌肯定要打完,因为一张攻击力最大的攻击牌就相当于没强化的强化牌

讨论一下抽到了几张强化牌

假设抽到了 $i$ 张强化牌,$k-i$ 张攻击牌

如果 $i < k$ 直接强化全打然后攻击就完事了,如果 $i \geq k$ 的话打最大的 $k-1$ 张强化和最大的一张攻击

由此可以 $dp$

设 $f_i$ 为 $i$ 张强化牌最多能扩的倍数,枚举当前抽到的强化牌 $j$,则

当 $i < k$ 时,$f_i = f_{i-1} + w_j \times f_j$

else, $f_i = f_i+f_{i-1}$

 

设 $g_i$ 为选了 $i$ 张攻击牌不翻倍的最大攻击力,枚举当前抽到的攻击牌 $j$,则

$g_i = g_{i-1} + C_{i-1}^{j-1} \times w_j + c$ (当 $i \leq (m-k+1)$ 时 $c=0$,$i>(m-k+1)$ 时 $c=g_{i-1}$)

答案就是 $\sum\limits_{i=0}^m f_i \times g_{m-i}$

第一个转移显然是按倍数从大到小排序,第二个需要把攻击力从小到大排序,

第一个转移,不管是怎么转移过来的,每张强化牌的贡献都是一样的,

第二个算每张牌贡献的时候,$c$ 标注了这张攻击牌打完之后还能不能再打别的攻击牌,如果不能打就是 $0$,能打的话要求跟他一起打的尽量大,这样转移能保证我们打的是一段尽量大的攻击牌

#include<bits/stdc++.h>
#define LL long long
#define rep(i,s,t) for(register int i = (s),i##end = (t); i <= i##end; ++i)
#define dwn(i,s,t) for(register int i = (s),i##end = (t); i >= i##end; --i)
using namespace std;const int mod = 998244353;
inline int read()
{int x=0,f=1;char ch;for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-f;for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';return x*f;
}
bool cmp(int a, int b) { return a > b; }
LL fac[3005], inv[3005];
int T, n, m, k, ans, f[3005], g[3005], w[3005];
LL C(int n, int m) { return fac[n] * inv[m] % mod * inv[n - m] % mod; }
int main() {fac[0] = fac[1] = inv[0] = inv[1] = 1;for (int i = 2; i <= 3000; i++) {fac[i] = fac[i - 1] * i % mod;inv[i] = ((LL)mod - mod / i) * inv[mod % i] % mod;}for (int i = 2; i <= 3000; i++) inv[i] = inv[i] * inv[i - 1] % mod;T = read();while (T--) {n = read(), m = read(), k = read();for (int i = 1; i <= n; i++) w[i] = read();sort(w + 1, w + n + 1, cmp);for (int i = 1; i <= max(n, m); i++) f[i] = 0;f[0] = 1;for (int i = 1; i <= n; i++)for (int j = min(m, i); j >= 1; j--)if (j <= k - 1)f[j] = (f[j] + (LL)f[j - 1] * w[i] % mod) % mod;elsef[j] = (f[j] + f[j - 1]) % mod;for (int i = 1; i <= n; i++) w[i] = read();sort(w + 1, w + n + 1);for (int i = 0; i <= max(n, m); i++) g[i] = 0;for (int i = 1; i <= n; i++)for (int j = min(m, i); j >= 1; j--)if (j <= m - (k - 1))g[j] = (g[j] + (LL)C(i - 1, j - 1) * w[i] % mod) % mod;elseg[j] = ((g[j] + g[j - 1]) % mod + (LL)C(i - 1, j - 1) * w[i] % mod) % mod;ans = 0;for (int i = 0; i <= m; i++) ans = (ans + (LL)f[i] * g[m - i] % mod) % mod;printf("%d\n", ans);}return 0;
}
View Code

 

当然比赛不会真的这么写...老老实实用两维状态前缀和优化,考后自然要选择好一点的写法

转载于:https://www.cnblogs.com/Kong-Ruo/p/10557008.html

这篇关于PKUSC2018 Slay The Spire的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/639464

相关文章

Spire.PDF for .NET【文档操作】演示:创建 PDF 文档

通过代码创建 PDF 文档具有多种优势。例如,您可以轻松合并动态内容,如用户输入、数据库记录或实时数据。基于代码的 PDF 生成允许更大的自定义和自动化,最大限度地减少创建高度定制文档时的手动干预。在本文中,您将学习如何使用Spire.PDF for .NET在 C# 和 VB.NET 中从头创建 PDF 文档。 Spire.PDF for .NET 是一款独立 PDF 控件,用于 .NET 程

Spire.PDF for .NET【文档操作】演示:创建标记的 PDF 文档

带标签的 PDF(也称为 PDF/UA)是一种包含底层标签树(类似于 HTML)的 PDF,用于定义文档的结构。这些标签可以帮助屏幕阅读器浏览整个文档而不会丢失任何信息。本文介绍如何使用Spire.PDF for .NET在 C# 和 VB.NET 中从头开始创建带标签的 PDF 。 Spire.PDF for .NET 是一款独立 PDF 控件,用于 .NET 程序中创建、编辑和操作 PDF

Spire.PDF for .NET【文档操作】演示:在 C# 中向 PDF 文件添加图层

Spire.PDF 完美支持将多页 PDF 拆分为单页。但是,更常见的情况是,您可能希望提取选定的页面范围并保存为新的 PDF 文档。在本文中,您将学习如何通过 Spire.PDF 在 C#、VB.NET 中根据页面范围拆分 PDF 文件。 Spire.PDF for .NET 是一款独立 PDF 控件,用于 .NET 程序中创建、编辑和操作 PDF 文档。使用 Spire.PDF 类库,开发人

Spire.PDF for .NET【文档操作】演示:创建 PDF/A 并插入图像的超链接

PDF/A 广泛用于 PDF 格式的长期归档。通过使用Spire.PDF,您可以直接创建PDF/A文件。本文主要介绍如何建立PDF/A文件;它还将演示如何在 C# 中添加图像和插入图像的超链接。 确保Spire.PDF for .NET(版本 2.9.43 或更高版本)已正确安装,然后通过以下路径在下载的 Bin 文件夹中添加 Spire.Pdf.dll 作为引用:“..\Spire.Pdf\B

Spire.PDF for .NET【文档操作】演示:合并 PDF 文档

需要合并 PDF 的原因有很多。例如,合并 PDF 文件允许您打印单个文件,而不是为打印机排队多个文档,组合相关文件通过减少要搜索和组织的文件数量来简化管理和存储多个文档的过程。在本文中,您将学习如何使用Spire.PDF for .NET将多个 PDF 文档合并为一个 PDF 文档,以及如何使用C# 和 VB.NET将不同 PDF 文档中的选定页面合并为一个 PDF 。 Spire.PDF f

Spire.PDF for .NET【文档操作】演示:合并 PDF 文件并添加页码

搜索了这么多有关 PDF 合并的信息后,很容易发现,无论您在线合并 PDF 文件还是使用 C#/VB.NET 来实现此任务,您都无法逃避对 PDF 文件安全等一些重要问题的担忧,因此需要花费多少时间或者合并后的文件是否支持打印页码等等。不过,只要来到这里,这些烦恼就不会出现。本节将专门向您介绍一种安全的解决方案,通过 .NET PDF 组件 Spire.PDF for .NET,使用 C#、VB.

PDF控件Spire.PDF for .NET【安全】演示:使用时间戳服务器对 PDF 进行数字签名

Spire.PDF for .NET 是一款独立 PDF 控件,用于 .NET 程序中创建、编辑和操作 PDF 文档。使用 Spire.PDF 类库,开发人员可以新建一个 PDF 文档或者对现有的 PDF 文档进行处理,且无需安装 Adobe Acrobat。 E-iceblue 功能类库Spire 系列文档处理组件均由中国本土团队研发,不依赖第三方软件,不受其他国家的技术或法律法规限制,同时适

「PKUSC2018」最大前缀和

题意 小 C 是一个算法竞赛爱好者,有一天小 C 遇到了一个非常难的问题:求一个序列的最大子段和。 但是小 C 并不会做这个题,于是小 C 决定把序列随机打乱,然后取序列的最大前缀和作为答案。 小 C 是一个非常有自知之明的人,他知道自己的算法完全不对,所以并不关心正确率,他只关心求出的解的期望值,现在请你帮他解决这个问题,由于答案可能非常复杂,所以你只需要输出答案乘上 n ! n! n!

PDF控件Spire.PDF for .NET【安全】演示:如何在 PDF 中添加签名字段

Spire.PDF for .NET 是一款独立 PDF 控件,用于 .NET 程序中创建、编辑和操作 PDF 文档。使用 Spire.PDF 类库,开发人员可以新建一个 PDF 文档或者对现有的 PDF 文档进行处理,且无需安装 Adobe Acrobat。 E-iceblue 功能类库Spire 系列文档处理组件均由中国本土团队研发,不依赖第三方软件,不受其他国家的技术或法律法规限制,同时适

note6:spire.pdf免费版

1、实现功能:对pdf文件抽取出指定页进行处理 2、问题:spire.pdf免费版不能处理超过10页的文件 <dependency><groupId>e-iceblue</groupId><artifactId>spire.pdf.free</artifactId><version>5.1.0</version></dependency> 【截图在公司内部软件上,不能外传,大概就是在文件第