加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

CF438E The Child and Binary Tree

发布时间:2020-12-14 04:37:16 所属栏目:大数据 来源:网络整理
导读:题目 生成函数就是好,什么题目都能搞 先来列一个暴力 (dp) , (dp_i) 表示形成 (i) 点权的二叉树的方案数 我们可以直接列出方程 [ dp_i=sum_{k=1}^nsum_{j=0}^{i-c_k}dp_jdp_{i-c_k-j} ] 边界条件 (dp_0=1) 发现里面类似卷积,于是生成函数来搞

题目

生成函数就是好,什么题目都能搞

先来列一个暴力(dp)(dp_i)表示形成(i)点权的二叉树的方案数

我们可以直接列出方程

[ dp_i=sum_{k=1}^nsum_{j=0}^{i-c_k}dp_jdp_{i-c_k-j} ]

边界条件(dp_0=1)

发现里面类似卷积,于是生成函数来搞

[ F(x)=sum_{i=0}([i=0]+sum_{k=1}^nsum_{j=0}^{i-c_k}dp_jdp_{i-c_k-j})x^i ]

[ F(x)=1+sum_{k=1}^nx^{c_k}sum_{j=0}^{i-c_k}dp_jx^jtimes dp_{i-c_k-j}x^{i-c_k-j} ]

发现里面就是(F^2(x)),于是

[ F(x)=1+sum_{k=1}^nx^{c_k}F^2(x) ]

发现有一个乘以(x^{c_k})之后再求和,设那个多项式为(G(x)),不就是卷上那边的那个多项式吗

[ F(x)=1+G(x)F^2(x) ]

于是我们可以解方程了

发现

[ F(x)=frac{1pm sqrt{1-4G(x)}}{2G(x)} ]

发现取正不收敛,于是

[ F(x)=frac{1- sqrt{1-4G(x)}}{2G(x)}=frac{4G(x)}{2G(x)(1+sqrt{1-4G(x)})}=frac{2}{1+sqrt{1-4G(x)}} ]

于是我们多项式求逆+多项式开根就能搞了

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int maxn=262144+1005;
inline int read() {
    char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const LL mod=998244353;
const LL G[2]={3,332748118};
LL A[maxn],B[maxn],C[maxn],K[maxn],D[maxn],H[maxn],T[maxn],F[maxn];
LL a[maxn],b[maxn];
int n,m,rev[maxn],len;
inline LL ksm(LL a,int b) {LL S=1;while(b){if(b&1) S=S*a%mod;b>>=1;a=a*a%mod;}return S;}
inline void NTT(LL *f,int o) {
    for(re int i=0;i<len;i++) if(i<rev[i]) std::swap(f[i],f[rev[i]]);
    for(re int i=2;i<=len;i<<=1) {
        int ln=i>>1;LL og1=ksm(G[o],(mod-1)/i);
        for(re int l=0;l<len;l+=i) {
            LL t,og=1;
            for(re int x=l;x<l+ln;x++) {
                t=(og*f[ln+x])%mod;
                f[ln+x]=(f[x]-t+mod)%mod;
                f[x]=(f[x]+t)%mod;
                og=(og*og1)%mod;
            }
        }
    }
    if(!o) return;
    LL inv=ksm(len,mod-2);
    for(re int i=0;i<len;i++) f[i]=(f[i]*inv)%mod;
}
inline void mul(LL *A,LL *B,int n) {
    len=1;while(len<n+n) len<<=1;
    for(re int i=0;i<len;i++) rev[i]=rev[i>>1]>>1|((i&1)?len>>1:0);
    NTT(A,0),NTT(B,0);
    for(re int i=0;i<len;i++) A[i]=(A[i]*B[i])%mod;
    NTT(A,1);for(re int i=n;i<len;i++) A[i]=0;
}
inline void Inv(int n,LL *A,LL *B) {
    if(n==1) {B[0]=ksm(A[0],mod-2);return;}
    Inv((n+1)>>1,A,B);
    memset(C,sizeof(C));memset(K,sizeof(K)),memset(D,sizeof(D));
    for(re int i=0;i<n;i++) C[i]=A[i],D[i]=K[i]=B[i];
    mul(K,C,n);mul(K,D,n);
    for(re int i=0;i<n;i++) B[i]=(2ll*B[i]-K[i]+mod)%mod;
}
inline void Sqrt(int n,LL *B) {
    if(n==1) {B[0]=1;return;}
    Sqrt((n+1)>>1,B);
    memset(H,sizeof(H));memset(F,sizeof(F));memset(T,sizeof(T));
    for(re int i=0;i<n;i++) F[i]=B[i],T[i]=2ll*B[i];
    Inv(n,T,H);mul(B,F,n);
    for(re int i=0;i<n;i++) B[i]=(B[i]+A[i])%mod;
    mul(B,H,n);
}
int main() {
    n=read(),m=read();
    for(re int i=1;i<=n;i++) a[read()]+=4;
    for(re int i=0;i<=m;i++) a[i]=mod-a[i],a[i]%=mod;
    a[0]++;Sqrt(m+1,a,A);A[0]++;Inv(m+1,b);
    for(re int i=1;i<=m;i++) printf("%lldn",2ll*b[i]%mod);
    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读