loj2538 「PKUWC2018」Slay the Spire 【dp】
题目链接
题解
比较明显的是,由于强化牌倍数大于\(1\),肯定是能用强化牌尽量用强化牌
如果强化牌大于等于\(k\),就留一个位给攻击牌
所以我们将两种牌分别排序,企图计算\(F(i,j)\)表示\(i\)张强化牌选出最强的\(j\)张的所有方案的倍数和
\(G(i,j)\)表示从\(i\)张攻击牌选出最强\(j\)张的所有方案的伤害和
那么
\]
所以我们只需计算出\(F\)和\(G\)
以\(F\)为例,我们枚举选出最后一张牌是什么
那么设\(f[i][j]\)表示用了\(i\)张强化牌,最后一张是\(j\)的倍数和
同样设\(g[i][j]\)表示用了\(i\)张攻击牌,最后一张是\(j\)的伤害和
那么有
\]
\]
可用前缀和优化为\(O(n^2)\)
那么
\]
\]
总复杂度\(O(Tn^2)\)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 3005,maxm = 100005,INF = 1000000000,P = 998244353;
inline int read(){
	int out = 0,flag = 1; char c = getchar();
	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
	return out * flag;
}
int n,m,K,fac[maxn],fv[maxn],inv[maxn];
int w1[maxn],w2[maxn];
int f[maxn][maxn],g[maxn][maxn];
int s[maxn];
void init(){
	fac[0] = fac[1] = inv[0] = inv[1] = fv[0] = fv[1] = 1;
	for (int i = 2; i <= 3000; i++){
		fac[i] = 1ll * fac[i - 1] * i % P;
		inv[i] = 1ll * (P - P / i) * inv[P % i] % P;
		fv[i] = 1ll * fv[i - 1] * inv[i] % P;
	}
}
inline int C(int n,int m){
	if (n < m) return 0;
	return 1ll * fac[n] * fv[m] % P * fv[n - m] % P;
}
inline int F(int x,int y){
	if (x > n || x < y) return 0;
	int re = 0;
	for (int i = 0; i <= n; i++)
		re = (re + 1ll * f[y][i] * C(n - i,x - y) % P) % P;
	return re;
}
inline int G(int x,int y){
	if (x > n || x < y) return 0;
	int re = 0;
	for (int i = 0; i <= n; i++)
		re = (re + 1ll * g[y][i] * C(n - i,x - y) % P) % P;
	return re;
}
inline bool cmp(const int& a,const int& b){
	return a > b;
}
void work(){
	sort(w1 + 1,w1 + 1 + n,cmp);
	sort(w2 + 1,w2 + 1 + n,cmp);
	for (int i = 0; i <= n; i++)
		for (int j = 0; j <= n; j++)
			f[i][j] = g[i][j] = 0;
	f[0][0] = 1;
	s[0] = 1;
	for (int i = 1; i <= n; i++) s[i] = s[i - 1];
	for (int i = 1; i <= n; i++){
		for (int j = i; j <= n; j++){
			f[i][j] = 1ll * w1[j] * s[j - 1] % P;
		}
		for (int j = 0; j < i; j++) s[j] = 0;
		for (int j = i; j <= n; j++) s[j] = (s[j - 1] + f[i][j]) % P;
	}
	s[0] = 0;
	for (int i = 1; i <= n; i++) s[i] = s[i - 1];
	for (int i = 1; i <= n; i++){
		for (int j = i; j <= n; j++){
			g[i][j] = (1ll * w2[j] * C(j - 1,i - 1) % P + s[j - 1]) % P;
		}
		for (int j = 0; j < i; j++) s[j] = 0;
		for (int j = i; j <= n; j++) s[j] = (s[j - 1] + g[i][j]) % P;
	}
	int ans = 0;
	for (int i = 0; i <= min(n,m); i++){
		int j = m - i; if (j < 0 || j > n) continue;
		if (i < K){
			ans = (ans + 1ll * F(i,i) * G(j,K - i) % P) % P;
		}
		else{
			ans = (ans + 1ll * F(i,K - 1) * G(j,1) % P) % P;
		}
	}
	printf("%d\n",ans);
}
int main(){
	init();
	int T = read();
	while (T--){
		n = read(); m = read(); K = read();
		REP(i,n) w1[i] = read();
		REP(i,n) w2[i] = read();
		work();
	}
	return 0;
}
												
											loj2538 「PKUWC2018」Slay the Spire 【dp】的更多相关文章
- LOJ2538. 「PKUWC2018」Slay the Spire【组合数学】
		
LINK 思路 首先因为式子后面把方案数乘上了 所以其实只用输出所有方案的攻击力总和 然后很显然可以用强化牌就尽量用 因为每次强化至少把下面的牌翻一倍,肯定是更优的 然后就只有两种情况 强化牌数量少于 ...
 - loj #2538. 「PKUWC2018」Slay the Spire
		
$ \color{#0066ff}{ 题目描述 }$ 九条可怜在玩一个很好玩的策略游戏:Slay the Spire,一开始九条可怜的卡组里有 \(2n\) 张牌,每张牌上都写着一个数字\(w_i\) ...
 - 【LOJ】#2538. 「PKUWC2018」Slay the Spire
		
题解 由于强化卡都是大于1的,我们分析一下就会发现,尽可能多的用强化卡,至少用一张攻击卡,一定是每组卡牌的最优选择 所以我们把攻击卡和强化卡从大到小排序 我们设\(g[i][j]\)表示前i张卡牌里选 ...
 - 「PKUWC2018」Slay the Spire
		
题目链接 题意分析 这个题其实不是期望 就是一共有\(C_{2n}^m\)种情况 每一种情况选择\(k\)张牌 然后求最大攻击值的总和 我们考虑 当前抽出了选出了\(i\)张强化牌 \(m-i\)张攻 ...
 - LOJ #2538. 「PKUWC 2018」Slay the Spire (期望dp)
		
Update on 1.5 学了 zhou888 的写法,真是又短又快. 并且空间是 \(O(n)\) 的,速度十分优秀. 题意 LOJ #2538. 「PKUWC 2018」Slay the Spi ...
 - loj2542 「PKUWC2018」随机游走  【树形dp + 状压dp + 数学】
		
题目链接 loj2542 题解 设\(f[i][S]\)表示从\(i\)节点出发,走完\(S\)集合中的点的期望步数 记\(de[i]\)为\(i\)的度数,\(E\)为边集,我们很容易写出状态转移方 ...
 - LOJ2542. 「PKUWC2018」随机游走【概率期望DP+Min-Max容斥(最值反演)】
		
题面 思路 我们可以把到每个点的期望步数算出来取max?但是直接算显然是不行的 那就可以用Min-Max来容斥一下 设\(g_{s}\)是从x到s中任意一个点的最小步数 设\(f_{s}\)是从x到s ...
 - Loj #2542. 「PKUWC2018」随机游走
		
Loj #2542. 「PKUWC2018」随机游走 题目描述 给定一棵 \(n\) 个结点的树,你从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去. 有 \(Q\) 次询问,每次 ...
 - 「PKUWC2018」随机游走(min-max容斥+FWT)
		
「PKUWC2018」随机游走(min-max容斥+FWT) 以后题目都换成这种「」形式啦,我觉得好看. 做过重返现世的应该看到就想到 \(min-max\) 容斥了吧. 没错,我是先学扩展形式再学特 ...
 
随机推荐
- spring cloud 入门系列:总结
			
从我第一次接触Spring Cloud到现在已经有3个多月了,当时是在博客园里面注册了账号,并且看到很多文章都在谈论微服务,因此我就去了解了下,最终决定开始学习Spring Cloud.我在一款阅读A ...
 - 占位符golang
			
定义示例类型和变量 type Human struct { Name string } var people = Human{Name:"zhangsan"} 普通占位符 占位符 ...
 - Linux(Contos7.5)环境搭建之JDK1.8安装(二)
			
1.下载安装包 wget -p 目录 url包地址 2.解压安装包 tar -xzvf 文件 -C 指定目录 3.修改名称 mv jdk1.8.0_45 jdk1.8 4.配置环境变量 vim /e ...
 - dumpe2fs命令详解
			
基础命令学习目录首页 dumpe2fs 显示ext2.ext3.ext4文件系统的超级快和块组信息.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE ...
 - 解决maven update project 后项目jdk变成1.5
			
http://blog.csdn.net/jay_1989/article/details/52687934
 - 基于NABCD评论作业-王者荣耀交流协会PSP DAILY
			
一.根据(不限于)NABCD评论作品的选题 N(Need,需求):在我知道PSP DAILY这款软件的时候,就认为这款软件对于学习软件工程课的学生来说有很大的需要.对于需求来说,软件工程课程中的学 ...
 - Daily Scrum 11.18
			
今日完成任务: 1.在提问问题的时候为问题创建索引 2.解决了修改个人资料后刷新没有更新的问题 3.初步加入了采纳功能(没完善UI设计) 遇到困难:创建索引之后,跳转到主页,需要重新登录,找了半天不知 ...
 - 20145214《网络对抗》MAL_后门原理与实践
			
20145214<网络对抗>MAL_后门原理与实践 基础问题回答 (1)例举你能想到的一个后门进入到你系统中的可能方式? 网页上查找资料时有时会不小心点到弹出来的广告,如果这个广告是个钓鱼 ...
 - 小组冲刺第十一天站立会议(发布Alpha版+网站链接)
			
注: “助成”招聘网站链接:http://58.87.74.131:8080/zhucheng 欢迎大家进行评测. 一.任务看板: 二.燃尽图: 三.团队成员合照: 四.任务总结: 今天我们发布网站B ...
 - 微服务注册与发现 —— eureka
			
基础概念 在微服务系统中,服务的注册和发现是第一步,常用的有: Eureka:https://github.com/Netflix/eureka Zookeeper:https://zookeeper ...