生成函数 + 多项式操作.
设 $F(i)$ 表示权值为 $i$ 的二叉树数目, $C(i)$ 表示 $i$ 这个数字是否在集合中出现过.
边界有 $F(0)=1$ ,转移时枚举根节点权值为 $i$ ,左子树权值为 $j$ .
$$
F(n)=\sum_{i=0}^n C(i)\sum_{j=0}^{n-i} F(j)F(n-i-j)
$$
这个式子和卡特兰数的递推式很像.
利用类似的做法求通项,把 $F,C$ 都看成多项式,得到
$$
F=CF^2+1 \\
F=\frac{1\pm \sqrt{1-4C}}{2C}
$$
考虑到边界条件 $C(0)=0,\lim _{x\to 0} F(x)=1$ ,可以发现此处应该取负号.
于是得到
$$
F=\frac{2}{1+\sqrt{1-4C}}
$$
用多项式开根 + 多项式求逆处理,时间复杂度 $O(n\log n)$ ,多项式开根可以直接套牛顿迭代来做.
1 | //%std |