「CTS2019」氪金手游

题目

点这里看题目。

分析

不难发现题目给出的边的结构是一棵树。题目要求的是在有向边限制下,每张牌第一次出现构成的序列是这棵树的一种拓扑序的方案数。

首先,对于这类题目,一个经典的结论是:

第 \(i\) 张牌有 \(W_i\) 的概率被抽出来。那么对于 \(S\subseteq U,S\not=\varnothing\),一张牌 \(x\in S\) 是 \(S\) 中第一个被抽出来的概率为:

\[\sum_{k\ge 0}\left(\frac{\sum_{z\in U}W_z-\sum_{y\in S}W_y}{\sum_{z\in U}W_z}\right)^k\cdot \frac{W_x}{\sum_{z\in U}W_z}=\frac{W_x}{\sum_{y\in S}W_y} \]

这个结论正向使用或者逆向使用都比较常见

一个想了半天的错误做法:

注意到最后答案只和 \(W\) 和一种拓扑序 \(\sigma\) 有关,我们可以直接写出答案:

\[\sum_\sigma\sum_W\left(\prod_{k=1}^np_{\sigma_k,W_k}\prod_{k=1}^nW_k\prod_{k=1}^n\left(\sum_{j=k}^nW_j\right)^{-1}\right) \]

然后可以提取公因数,外层枚举 \(W\),内层只需要枚举 \(\sigma\)。这个时候可能就可以开始 DP 了,只需要能够成功维护 \(\sum_\sigma \prod_k p_{\sigma_k,W_k}\) 即可,但是这个东西一点都不简单。

稍微研究一下这个不对的方向,我们发现,最大的错误出在没有联系树结构,而仅仅考虑了抽象的拓扑序 \(\sigma\)。现在我们应当回过头,重新审视一下“树”。

不妨从一个简单的情况开始考虑,我们可以完成“树是外向树”的问题吗?这个时候就要求,结点 \(u\) 必须早于它的所有儿子被取到。套用一下结论,如果 \(u\) 子树内包括 \(u\) 的 \(\sum W\) 为 \(S\),那么此时的概率就是 \(\frac{W_u}{S}\)。现在我们只需要简单地维护 \(dp_{u,s}\),表示 \(u\) 的子树内,\(S=s\) 的情况的概率之和即可。

那么,一般的树和上述情况的区别就在于,一般的树可以有反向边。但是,如果我们根本不管反向边的限制,那么原树就被划分为了若干个独立的连通块,分别计算并乘起来;此时多半会有不合反向边限制的情况,我们可以钦定某些反向边性质被打破,于是反向边就变成了正向边......不难发现,这个算法描述的正是一个容斥的过程。当然,我们大可不必枚举某些反向边云云,直接在遇到反向边的时候,修改 DP 的转移方程,把容斥算进去就可以了。

小结:

  1. 充分利用已知的结构。比如此题,拓扑序背后还是树结构,如果忽略树结构那么拓扑序本身就会变得非常晦涩;当然,也要学会掉头
上一篇:Spoj-DWARFLOG Manipulate Dwarfs


下一篇:[ARC089D] ColoringBalls