P8329 ZJOI2022 D1T1 树 题解

算法一

状压 DP,naive 的,不写。

预计得分:20pts.

实际得分:20pts.

算法二

比较简单的 DP 想法,其实也是比较好想的,场上细节没写好。

显然有一个 \(dp_{i,j,k}\) 表示 \(i\) 个节点,第一个树中 \(j\) 个节点预计是非叶子,但是目前还是叶子,第二个树中 有 \(k\) 个根(因为是从 \(n\sim 1\)来写的,所以需要从下到上的放点,所以放点的时候需要合并子树。)

然而不能转移。因为非叶子,叶子但预计非叶子,叶子且预计叶子,三种点肯定是不同的,而我们只枚举了一个点,显然不行。

故设计 \(dp_{i,j,k,t}\) 表示 \(i\) 个节点,第一个树中 \(j\) 个节点预计是非叶子,但是目前还是叶子,且有 \(t\) 个非叶子,第二个树中有 \(k\) 个根。

这样转移简单的,这里用刷表。

核心代码:

int Co = C[o][o - l + 1];
if (l != o + 1) {
(dp[(i + 1) & 1][j][k][l] += dp[i & 1][j][k][o] * j % mod * Co % mod) %= mod;
if (k)(dp[(i + 1) & 1][j + 1][k - 1][l] +=dp[i & 1][j][k][o] * k % mod * Co % mod) %= mod;
} else {
 (dp[(i + 1) & 1][j][k + 1][l] += dp[i & 1][j][k][o] * j % mod * Co % mod) %= mod;
 (dp[(i + 1) & 1][j + 1][k][l] += dp[i & 1][j][k][o] * k % mod * Co % mod) %= mod;
}

时间复杂度 \(O(n^5)\)

预计得分:40pts.

实际得分:40-60pts.

算法三

先假设只有一棵树,然后限制是否为叶子的情况。

\(i\) 个限制为 \(a_i\)

显然有

\[dp_{i,j}=\left\{ \begin{aligned} dp_{i-1,j}\times j + dp_{i-1,j+1}\times (j+1),a_i=1 \\ dp_{i-1,j}\times j + dp_{i-1,j-1}\times (j-1),a_i=0 \\ \end{aligned} \right. \]

那我是否可以将问题规约成以下问题。

\(f_{0} = f_{n} = 0\)

\(a_i=1\),\(f_i = f_{i-1},f_{i-1}+1\)

\(a_i=0\),\(f_{i} = f_{i-1},f_{i-1}-1\)

求所有可能的 \(f\) 序列的和。

发现这个规约可以将两个树合并起来。

\(dp_{i,j,k}\) 表示 \(i\) 个点,第一个树的 \(f_i = j\),第二个树的 \(f_{i+1} = k\)

\(i+1\) 是因为第二个树是倒着转移的,所以第一个出现 \(i\) 是和 \(i+1\) 所连接的。

转移不难。

时间复杂度 \(O(n^3)\)

预计得分:100pts.

实际得分:100pts.

posted @ 2026-05-13 19:05  hnczy  阅读(15)  评论(0)    收藏  举报