一道神奇的树形dp题

题目大意:给定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过程,恩,这个很好玩。

http://www.zhengruioi.com/submission/4580

 

考虑一个朴素dp[i][j]表示向左不超过i次叶子数量j,那么dp[i][j]=\sum_{k=1}^{i-1}dp[i-1][k]*dp[i][j-k],因此设F_i(x)为dp[i]的生成函数,那么F_i(x)=F_{i-1}(x)F_i(x)+x,也就是F_i(x)=xF_{i-1}(x)/(1-F_{i-1}(x)),这样F可以矩乘,代入若干单位根矩乘,然后IDFT回来。或者直接找一下规律,发现F的分子分母的系数就是斜着的组合数,可以直接求出,这样直接求逆就可以O(klgk+nlgn)。

事实上还可以做到O(klgnklgn)求单项,做法类似常系数线性递推。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值