PKUWC都是神仙题,蒟蒻我根本做不来。
传送门
Minimax
Slay the Spire
随机算法
随机游走
猎人杀
斗地主
Minimax
题解
答案的表达式看上去极其诡异,但是观察过后,不难发现,只要求出每种权值出现的概率,问题就迎刃而解了(废话)。
首先需要抓住题目中保证的两个性质,一个是权值互不相同,另一个是有儿子的节点最多只有两个儿子。
设第$i$个节点出现权值$j$的概率为$g_{i,j}$,那么由于权值互不相同,左右儿子中最多只有一个节点可能出现权值$j$。
设左儿子的编号为$L$,右儿子为$R$,如果左儿子可能出现权值$j$,那么就有:
右儿子可能出现权值$j$的情况同理。
考虑这个转移的过程,相当于权值$j$出现的概率被乘上了
仔细观察这个式子,里面是一个前缀和和一个后缀和,所以可以通过对支持乘法操作的线段树进行合并操作来实现转移,不断向上合并之后就可以求出根节点每种权值出现的概率了。具体实现参见代码(感觉还是挺妙的)。
时间复杂度和空间复杂度都是$O(n\log n)$。
代码
1 |
|
Slay the Spire
题解
首先考虑一下,在抽到了$m$张牌之后,怎样打才比较优。
不难发现,肯定挑权值大的牌打,所有要打的攻击牌肯定都是在要打的强化牌打完之后才打的。
并且,由于强化牌上的数字最少为$2$,所以如果抽到的强化牌数量够多的话,一定会打出权值前$k-1$大的强化牌,然后再打出一张权值最大的攻击牌;如果抽到的强化牌数量比较少,那肯定会全部打出。
首先对两种牌的权值从大到小排序。
设权值第$i$大强化牌的权值为$p_i$,权值第$i$大的攻击牌的权值为$w_i$。
考虑两个DP:
- $F[i][j][0/1]$:表示考虑了前$i$张强化牌,打出了$j$张,第$i$张强化牌没打/打了时所有方案强化牌的乘积的和。
- $G[i][j][0/1]$:表示考虑了前$i$张攻击牌,打出了$j$张,第$i$张攻击牌没打/打了时所有方案攻击牌的加和的和。
不难推出转移方程:
上述两个数组处理好之后,可以开始考虑计算答案了。
首先可以枚举一下抽中的牌中强化牌的数量,设共$i$张,分两种情况考虑:
$i<k$,那么这种情况对答案的贡献为:
$i\geq k$,此时的贡献为:
累加起来即可得到答案。
代码
1 |
|
随机算法
题解
排列的总数很好求,考虑有多少种排列能求出正确的答案。
数据范围很小,考虑一个状压DP:
$F[S][i]$表示当前的排列中已经包含了集合$S$中的所有元素,且最大独立的大小为$i$的方案数。
枚举下一个不在$S$中的节点$j$,使节点$j$加入到最大独立集中来。设$j$以及与$j$距离为$1$的点构成的集合为$T$,那么节点$j$需要放在排列中最靠前的一个空位,剩下的节点可以随意放排列中剩余的空位上。所以就有转移:
初始有$F[0][0]=1$,最后的答案为$\frac{F[U][mx]}{n!}$,其中$U$为全集,$mx$为最大独立集的大小。
代码
1 |
|
随机游走
题解
题目中要求经过$S$中所有点的期望步数,即$E(max(S))$,并不好搞,考虑到数据范围非常小,可以使用MinMax容斥,即$E(\max(S))=\sum_{T\subseteq S{}}(-1)^{|T|+1}E(\min(T))$,所以问题就转化为了求从起点出发,经过$T$中任意一个节点的期望步数。
首先可以暴力枚举集合$T$,然后考虑一个树形DP:
$F_i$表示从节点$i$出发,经过集合$T$中任意一个节点的期望步数,比较显然的转移是:
- 若$i\notin T$:
- $i\in T$
考虑第一种情况,这个式子不是很好看,考虑分离儿子与父亲的情况分别考虑。
设$F[i]=K[i]\cdot F[fa[i]]+B[i]$,那么就有:
其中$SumK[i]$表示$\sum_{j\in son[i]}{K[j]}$,$SumB[i]$同理。
所以就有:
这两个数的取值与$i$的父节点无关,只与子节点有关。
对于第二中情况,显然有$K[i]=B[i]=F[i]=0$。
所以就可以通过一趟$DFS$来求出每个节点的$K[i]$与$B[i]$。
对根节点$x$,因为没有父亲,所以就有$F[x]=B[x]$。
所以我们就可以求出所有集合$T$的期望,以及他们对答案的贡献。
但是由于询问数量很多,不能每次都暴力枚举子集。
不难发现,对于一个集合$T$,他是否会对$S$产生贡献以及贡献的大小只取决$T$是不是$S$的子集以及$T$本身。
所以我们可以先预处理出所有$2^n$个子集的贡献,然后就可以通过高维前缀和来快速统计每一个询问的答案了。
时间复杂度$O(n\cdot 2^n)$。
代码
1 |
|
猎人杀
题解
对于这一道题,一个比较麻烦的问题就是当死了猎人之后,每个猎人的中枪概率会发生改变。
不妨对问题进行这样的转化:
当猎人中枪之后,他的尸体还在,并且在下一次开枪的时候,他的尸体仍然有机会被打中,打中的概率不变。如果一次开枪打中了一具尸体,那么就继续开枪,直到打到活人为止。
不难发现,这样转化问题之后,问题的答案并没有改变,而且此时每次猎人中枪的概率没变。
并且直接计算$1$号猎人最后死亡的概率并不容易,考虑容斥:
考虑如何计算一个集合内的所有猎人都在$1$号猎人之后死的概率。
令$S=\sum{i=1}^{n}w_i$,$W_T=\sum{i\in T}W_i$,那么就有:
所以,集合$T$对答案的贡献只与$W_T$和$|T|$有关。
但是数据范围非常大,直接背包肯定是不行的,考虑生成函数:
那么就有
那个生成函数直接用NTT或者FFT然后分治计算一下就好了,时间复杂度$O(n\log^2n)$。
代码
1 |
|
斗地主
神仙题,蒟蒻我太菜了,做不来。