ABC222H 题解

很久之前我问 joke3579 有没有什么水黑,然后他给我了这个题。小推一波。

题解

看到这种东西首先找找有没有什么性质。简单分析可以得出一棵美丽的 \(n\) 阶二叉树一定满足如下性质:

  1. 根节点和叶子节点都为 \(1\)
  2. 整棵树所有节点权值和为 \(n\)
  3. 每个 \(1\) 都可以转移到同样是 \(1\) 的祖先,也就是没有两个相邻的 \(0\)

那根据这个可以设计一波 dp。设 \(dp_{n,1}\) 为所有美丽 \(n\) 阶二叉树个数,\(dp_{n,0}\) 为根节点为 \(0\),其余性质都满足的二叉树个数。那么转移考虑合并两棵二叉树:

  1. 根是 \(0\)\(dp_{n,0}=2dp_{n,1}+\sum_{i=1}^{n-1}dp_{i,1}dp_{n-i,1}\)
  2. 根是 \(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;
}
posted @ 2023-02-16 06:51  gtm1514  阅读(30)  评论(0编辑  收藏  举报