很久之前我问 joke3579 有没有什么水黑,然后他给我了这个题。小推一波。
题解
看到这种东西首先找找有没有什么性质。简单分析可以得出一棵美丽的 \(n\) 阶二叉树一定满足如下性质:
- 根节点和叶子节点都为 \(1\)。
- 整棵树所有节点权值和为 \(n\)。
- 每个 \(1\) 都可以转移到同样是 \(1\) 的祖先,也就是没有两个相邻的 \(0\)。
那根据这个可以设计一波 dp。设 \(dp_{n,1}\) 为所有美丽 \(n\) 阶二叉树个数,\(dp_{n,0}\) 为根节点为 \(0\),其余性质都满足的二叉树个数。那么转移考虑合并两棵二叉树:
- 根是 \(0\):\(dp_{n,0}=2dp_{n,1}+\sum_{i=1}^{n-1}dp_{i,1}dp_{n-i,1}\)
- 根是 \(1\):\(dp_{n,1}=2(dp_{n-1,0}+dp_{n-1,1})+\sum_{i=1}^{n-2}(dp_{i,0}+dp_{i,1})(dp_{n-i-1,0}+dp_{n-i-1,1})\)
初值显然 \(dp_{1,0}=0,dp_{n,1}=1\)。
那看后边这个东西一脸卷积的样子,考虑用生成函数刻画。设
\[F_0(x)=\sum_{i=0}f_{i,0}x^i \]\[F_1(x)=\sum_{i=0}f_{i,1}x^i \]那么上边两个转移式子可以写成:
\[F_0=2F_1+F_1^2 \]\[\begin{aligned} F_1=&x+2x(F_0+F_1)+x(F_0+F_1)^2\\ =&x(F_0+F_1+1)^2\\ =&x(F_1^2+3F_1+1)^2 \end{aligned} \]那么显然 \(x=\dfrac{F_1}{(F_1^2+3F_1+1)^2}\)。自然得到 \(F_1\) 的复合逆
\[G=\frac x{(x^2+3x+1)^2} \]套路拉格朗日反演提取系数:
\[\begin{aligned} [x^n]F_1=&\frac 1n[x^{n-1}]\left(\frac x{G}\right)^n\\ =&\frac 1n[x^{n-1}](x^2+3x+1)^{2n}\\ =&\frac 1n[x^{n-1}]\sum_{i=0}^{2n}\binom{2n}ix^{2i}\sum_{j=0}^{2n-i}\binom{2n-i}j(3x)^j\\ =&\frac 1n\sum_{i=0}^{2n}\binom{2n}i\sum_{j=0}^{2n-i}\binom{2n-i}j3^j[2i+j=n-1]\\ =&\frac 1n\sum_{2i+1\le n}\binom{2n}i\binom{2n-i}{n-1-2i}3^{n-1-2i} \end{aligned} \]可以 \(O(n)\) 计算。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int mod=998244353;
int n,ans,jc[20000010],inv[20000010],pw[20000010];
int C(int n,int m){
return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}
int main(){
scanf("%d",&n);
jc[0]=inv[0]=pw[0]=1;
jc[1]=inv[1]=1;pw[1]=3;
for(int i=2;i<=2*n;i++){
jc[i]=1ll*jc[i-1]*i%mod;
inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
pw[i]=1ll*pw[i-1]*pw[1]%mod;
}
for(int i=1;i<=2*n;i++)inv[i]=1ll*inv[i-1]*inv[i]%mod;
for(int i=0;2*i+1<=n;i++){
ans=(ans+1ll*C(2*n,i)*C(2*n-i,n-1-2*i)%mod*pw[n-1-2*i])%mod;
}
ans=1ll*ans*inv[n]%mod*jc[n-1]%mod;
printf("%d\n",ans);
return 0;
}
标签:frac,int,题解,sum,ABC222H,2n,binom,dp
From: https://www.cnblogs.com/gtm1514/p/17125344.html