【做题记录】国家集训队2011 Crash的文明世界
-
【国家集训队 \(2011\)】\(\text{Crash}\) 的文明世界
- 算法:第二类斯特林数、换根 \(\text{dp}\)
题目:
给出一棵 \(n\) 个点的树,求对于每个点 \(i\) 的 \(d(i)\) 值。
\(1\leq n\leq 50000,1\leq k\leq 150\)
题解:
首先对于第二类斯特林数有一个性质:
这个性质很显然。\(n^k\) 表示将 \(k\) 个球放入 \(n\) 个盒子。
然后枚举 \(k\) 个球放入盒子的盒数,即 \(i\)。然后将 \(k\) 个球放入 \(i\) 个盒子里,每个盒子非空,即为 \(\begin{Bmatrix}k\\i\end{Bmatrix}\)。然后从 \(n\) 个盒子中选出 \(i\) 个盒子又有 \(\begin{pmatrix}n\\i\end{pmatrix}\) 种,又因为盒子不同所以还要再乘上 \(i!\)。
对于题目所求的式子,我们不妨将这个性质代入 \(\text{dis}(x,i)^k\),得
然后题目的 \(k\) 非常小,所以对于 \(\sum\limits_{l=0}^{k}l!\begin{Bmatrix}k\\l\end{Bmatrix}\) 你可以随便搞暴力,反正 \(l!\) 和 \(\begin{Bmatrix}k\\l\end{Bmatrix}\) 都可以预处理出来嘛。
因为 \(k\) 实在是太小了,所以你甚至用 \(\begin{Bmatrix}n\\m\end{Bmatrix}=\begin{Bmatrix}n-1\\m-1\end{Bmatrix}+m\begin{Bmatrix}n-1\\m\end{Bmatrix}\) 递推式 \(O(k^2)\) 都可以过。
然后观察剩下的。
不妨考虑 \(\text{dp}\) 转移,设 \(u\in tr_i\) 表示 \(u\) 在 \(i\) 的子树内,\(u\in son_i\) 表示 \(u\) 是 \(i\) 的其中一个儿子,那么设
根据组合数最基本的式子,
有
即
然后换根 \(\text{dp}\),即上一次转移中的父亲成为这次转移中的儿子,最后一直推下去即可。
总的时间复杂度分两块:
- 预处理第二类斯特林数和阶乘,\(O(k^2)\)(这里是用递推式来做的)
- 换根 \(\text{dp}\),\(O(nk)\)
总时间复杂度为 \(O(nk+k^2)\)。