一道神奇的树形dp题

来源:互联网 发布:安卓ocr软件 编辑:程序博客网 时间:2024/06/07 23:15

题目大意:给定n,m,对于1~n中的每一个k,求有k个叶子结点且满足以下性质的二叉树的个数:

1)一个点要么是叶子结点,要么有左右儿子。

2)从根出发的任意一条路径上,向左的边不超过m次。

对998244353取模。n,m<=5000。

题解如下:

首先容易想到dp[x][y]表示x个叶子最远向左走y次的方案数,然后转移枚举左边子树的叶子个数,用容斥剪掉重复计算部分。

发现这个转移是卷积的形式,可以用ntt优化卷积,这样是过不了了。


然后就是神dp。现在我们考虑模拟树的dfs来构造这棵树。

令dp[x][y]表示节点数为x,根到当前结点向左走了y次。

首先显然这棵树的大小是2k-1,这是毫无置疑的。

然后考虑发现如果按照先序遍历的方式dfs这棵树的话,那么:

如果当前这个点x向左走到y,那么x之后一定会向右走到z。

也就是说,对于每一个点,要么向左走,并且x++,y++;

而从当前x这个点向右走,可以认为是从y向上一步(y--),然后向右一步(x++)。

这时因为如果一个点向右走说明从这个点向左走过,并且已经走完了,所以一定存在一个回溯过程。

事实上还可以直接令dp[x][y]表示叶子数为x向左走y。这样从x向左走叶子数量不变,向右走叶子数量+1.

这样复杂度就是O(n^2)的。

感觉这种题不是很可做啊。

维护树的dfs过程,恩,这个很好玩。