先从最朴素的 DP 出发。
设 fn 表示恰有 n 个叶子的所有合法二叉树的美观度之和。
再定义权值函数
w(x)={vi,A,x=si,否则。
那么一棵有 n 个叶子的树,根节点的左子树可以有 j 个叶子,右子树有 n−j 个叶子,其中 1≤j≤n−1。
根节点的贡献是 w(j),左右子树的贡献分别是 fj,fn−j,于是有
f1=1,
fn=j=1∑n−1w(j)fjfn−j(n≥2)。
这就是最直接的做法。时间复杂度 O(n2),可以通过小数据。
先拆掉“默认值 A”
这题的关键在于:真正特殊的位置只有 k≤10 个。
令
bx=w(x)−A。
于是只有当 x=si 时,bx=0;其余位置 bx=0。
转移式可以写成
fn=Aj=1∑n−1fjfn−j+j=1∑n−1bjfjfn−j。
第二项只有很少几个位置有贡献,这是后面优化的突破口。
如果 A=0,那么第一项直接消失,只剩下特殊位置转移:
fn=j=1∑n−1bjfjfn−j。
由于非零的 bj 只有 k 个,所以直接枚举这些位置即可,复杂度 O(nk)。
下面只讨论 A=0 的情况。
生成函数
定义生成函数
F(x)=n≥1∑fnxn。
再定义
P(x)=n≥1∑bnfnxn。
注意到 P(x) 只有至多 k 个非零项,因为只有 n=si 时 bn 才非零。
由递推式直接得到
F(x)=x+AF(x)2+P(x)F(x)。
整理一下:
AF(x)2−(1−P(x))F(x)+x=0。
这是一个关于 F(x) 的二次方程。仿照求 Catalan 生成函数的写法,设
S(x)=1−P(x)−2AF(x)。
那么有
S(x)2=(1−P(x))2−4Ax。
记
D(x)=(1−P(x))2−4Ax。
于是
S(x)2=D(x)。
现在问题就变成:已知一个非常稀疏的多项式 D(x)(系数非 0 的项只有 O(k2) 个),要求出它的平方根 S(x) 的各项系数。
从 S(x)2=D(x) 推系数递推
设
S(x)=1+n≥1∑snxn,D(x)=1+n≥1∑dnxn。
直接平方比较系数会得到一个卷积,还是太慢。这里用一个常见技巧:对
S(x)2=D(x)
两边求导,得到
2S(x)S′(x)=D′(x)。
再乘上 S(x),整理为
2D(x)S′(x)=D′(x)S(x)。
比较 xn−1 的系数,可以得到
2nsn=ndn+t=1∑n−1(3t−2n)dtsn−t。
由于 dt 只有 O(k2) 个非零项,所以求每个 sn 时,求和只需要枚举这些非零项,单次复杂度是 O(k2)。
如何从 sn 还原 fn
由定义
S(x)=1−P(x)−2AF(x)
可知
sn=−2Afn−[xn]P(x)。
如果 n 不是特殊位置,那么 [xn]P(x)=0,于是
sn=−2Afn。
如果 n=si 是特殊位置,那么
[xn]P(x)=(vi−A)fn。
总时间复杂度为 O(nk2)。