题目链接:洛谷 CF原网

题目大意:有 $n$ 个互不相同的正整数 $c_i$。问对于每一个 $1\le i\le m$,有多少个不同形态(考虑结构和点权)的二叉树满足每个点权都在 $c$ 中出现过,且点权和为 $i$。答案对 $998244353$ 取模。

$1\le n,m\le 10^5$。


首先考虑DP,$f_i$ 表示点权和为 $i$ 的树数。

那么枚举根节点的点权和两棵子树的点权和 $f_k=\sum\limits^n_{i=1}c_i\sum\limits^{k-c_i}_{j=0}f_jf_{k-c_i-j}$。

初始状态 $f_0=1$。因为空树也能作为子树。

这样的复杂度是 $O(nm^2)$,不能过。

考虑 $c$ 的生成函数 $C(x)=\sum x^{c_i}$ 和 $f$ 的生成函数 $F(x)=\sum f_ix^i$。(你问我怎么想到的?我也不知道啊)

那么容易发现原来的式子就是几个函数的卷积。

$F=C\times F\times F+1$(注意 $f_0=1$)

$C\times F^2-F+1=0$

$F=\dfrac{1\pm\sqrt{1-4C}}{2C}$

接下来看看上面该取正还是负。

取正时 $\lim\limits_{x\rightarrow 0}F(x)=+\infty$,不收敛,舍去。

取负时 $\lim\limits_{x\rightarrow 0}F(x)=1$,符合题意。

那么 $F=\dfrac{1-\sqrt{1-4C}}{2C}=\dfrac{2}{1+\sqrt{1-4C}}$。

直接套模板即可。时间复杂度 $O(m\log m)$。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=,mod=;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
char ch=getchar();int x=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
int n,m,c[maxn],lim,l,rev[maxn],invtmp[maxn],Binv[maxn],sqrtmp[maxn],Csqrt[maxn],Cinv[maxn];
inline void init(int upr){
for(lim=,l=;lim<upr;lim<<=,l++);
FOR(i,,lim-) rev[i]=(rev[i>>]>>)|((i&)<<(l-));
}
inline int add(int a,int b){return a+b<mod?a+b:a+b-mod;}
inline int sub(int a,int b){return a<b?a-b+mod:a-b;}
inline int qpow(int a,int b){
int ans=;
for(;b;b>>=,a=1ll*a*a%mod) if(b&) ans=1ll*ans*a%mod;
return ans;
}
void NTT(int *A,int tp){
FOR(i,,lim-) if(i<rev[i]) swap(A[i],A[rev[i]]);
for(int i=;i<lim;i<<=)
for(int j=,r=i<<,Wn=qpow(,mod-+tp*(mod-)/r);j<lim;j+=r)
for(int k=,w=;k<i;k++,w=1ll*w*Wn%mod){
int x=A[j+k],y=1ll*A[i+j+k]*w%mod;
A[j+k]=add(x,y);A[i+j+k]=sub(x,y);
}
if(tp==-) for(int i=,linv=qpow(lim,mod-);i<lim;i++) A[i]=1ll*A[i]*linv%mod;
}
void poly_inv(int *A,int *B,int deg){
if(deg==) return void(B[]=qpow(A[],mod-));
poly_inv(A,B,(deg+)>>);
init(deg<<);
FOR(i,,deg-) invtmp[i]=A[i];
FOR(i,deg,lim-) invtmp[i]=;
NTT(invtmp,);NTT(B,);
FOR(i,,lim-) B[i]=1ll*sub(,1ll*invtmp[i]*B[i]%mod)*B[i]%mod;
NTT(B,-);
FOR(i,deg,lim-) B[i]=;
}
void poly_sqrt(int *A,int *B,int deg){
if(deg==) return void(B[]=);
poly_sqrt(A,B,(deg+)>>);
init(deg<<);
FOR(i,,lim-) Binv[i]=;
poly_inv(B,Binv,deg);
init(deg<<);
FOR(i,,deg-) sqrtmp[i]=A[i];
FOR(i,deg,lim-) Binv[i]=sqrtmp[i]=;
NTT(sqrtmp,);NTT(Binv,);
FOR(i,,lim-) sqrtmp[i]=1ll*sqrtmp[i]*Binv[i]%mod;
NTT(sqrtmp,-);
FOR(i,,deg-) B[i]=499122177ll*add(B[i],sqrtmp[i])%mod;
FOR(i,deg,lim-) B[i]=;
}
int main(){
n=read();m=read();
FOR(i,,n){
int x=read();
if(x<=m) c[x]=;
}
FOR(i,,m) c[i]=(mod-4ll*c[i]%mod)%mod;
c[]=;
poly_sqrt(c,Csqrt,m+);
Csqrt[]=add(Csqrt[],);
poly_inv(Csqrt,Cinv,m+);
FOR(i,,m) printf("%d\n",add(Cinv[i],Cinv[i]));
}

CF438E The Child and Binary Tree(生成函数,NTT)的更多相关文章

  1. CF438E The Child and Binary Tree 生成函数、多项式开根

    传送门 设生成函数\(C(x) = \sum\limits_{i=0}^\infty [\exists c_j = i]x^i\),答案数组为\(f_1 , f_2 , ..., f_m\),\(F( ...

  2. cf438E. The Child and Binary Tree(生成函数 多项式开根 多项式求逆)

    题意 链接 Sol 生成函数博大精深Orz 我们设\(f(i)\)表示权值为\(i\)的二叉树数量,转移的时候可以枚举一下根节点 \(f(n) = \sum_{w \in C_1 \dots C_n} ...

  3. [题解] CF438E The Child and Binary Tree

    CF438E The Child and Binary Tree Description 给一个大小为\(n\)的序列\(C\),保证\(C\)中每个元素各不相同,现在你要统计点权全在\(C\)中,且 ...

  4. CF438E The Child and Binary Tree(生成函数+多项式开根+多项式求逆)

    传送门 可以……这很多项式开根模板……而且也完全不知道大佬们怎么把这题的式子推出来的…… 首先,这题需要多项式开根和多项式求逆.多项式求逆看这里->这里,这里讲一讲多项式开根 多项式开方:已知多 ...

  5. Codeforces 438E The Child and Binary Tree - 生成函数 - 多项式

    题目传送门 传送点I 传送点II 传送点III 题目大意 每个点的权值$c\in {c_{1}, c_{2}, \cdots, c_{n}}$,问对于每个$1\leqslant s\leqslant ...

  6. CF438E The Child and Binary Tree

    思路 设F(x)的第x项系数为权值和为x的答案 题目中要求权值必须在集合中出现,这个不好处理,考虑再设一个C,C的第x项如果是1代表x出现在值域里,如果是0,代表x没有出现在值域里,然后由于二叉树可以 ...

  7. 【CF438E】The Child and Binary Tree(多项式运算,生成函数)

    [CF438E]The Child and Binary Tree(多项式运算,生成函数) 题面 有一个大小为\(n\)的集合\(S\) 问所有点权都在集合中,并且点权之和分别为\([0,m]\)的二 ...

  8. Codeforces 250 E. The Child and Binary Tree [多项式开根 生成函数]

    CF Round250 E. The Child and Binary Tree 题意:n种权值集合C, 求点权值和为1...m的二叉树的个数, 形态不同的二叉树不同. 也就是说:不带标号,孩子有序 ...

  9. [codeforces438E]The Child and Binary Tree

    [codeforces438E]The Child and Binary Tree 试题描述 Our child likes computer science very much, especiall ...

随机推荐

  1. [Oracle][Corruption]发生ORA00600[kdsgrp1]的时候,如何进行调查

    本质上,这很可能是坏块引发的,所以需要调查 关联的Table 中的坏块状况: Excerpt of trace file============================*** 2017-08- ...

  2. 并行编程(Parallel Framework)

    前言 并行编程:通过编码方式利用多核或多处理器称为并行编程,多线程概念的一个子集. 并行处理:把正在执行的大量的任务分割成小块,分配给多个同时运行的线程.多线程的一种. 并行编程分为如下几个结构: 1 ...

  3. 记一次在.NET成长之路上的下午茶

    在2017年2月25日我和李海国有幸与阳铭.朱永光两位大哥喝了一次下午茶.熟悉ABP框架的朋友呢知道阳铭远在上海,所以个人很是珍惜这次机会.朱永光大哥是微软MVP,之前是启路科技的CTO,目前在微软. ...

  4. Ionic 入门与实战之第三章:Ionic 项目结构以及路由配置

    原文发表于我的技术博客 本文是「Ionic 入门与实战」系列连载的第三章,主要对 Ionic 的项目结构作了介绍,并讲解了Ionic 中的路由概念以及相关配置. 原文发表于我的技术博客 1. Ioni ...

  5. Mongo 开发笔记

    时间 程序的时间是本地时间 ,数据库中的时间是 ISO 标准时间 . ISO时间 + 8 小时 = 本地时间(北京时间 ) Java驱动会自动做转化. 语法 数组查询 数据查询使用 elemMatch ...

  6. Python_试题_23

    # Python基础数据类型考试题# 考试时间:两个半小时 满分100分(80分以上包含80分及格)# 一,基础题.# 1,简述变量命名规范(3分)# 答:变量名是由数字.字母.下划线任意组合,变量名 ...

  7. Linux内核分析第三周学习总结

    Linux内核源码简介 arch/ 该目录中包含和硬件体系结构相关的代码,每种平台占一个相应的目录. 和32位PC相关的代码存放在x86目录下. 每种平台至少包含3个子目录:kernel(存放支持体系 ...

  8. type=hidden

    非常值得注意的一个,通常称为隐藏域:如果一个非常重要的信息需要被提交到下一页,但又不能或者无法明示的时候. 一句话,你在页面中是看不到hidden在哪里.最有用的是hidden的值.

  9. org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unexpected failure during bean definition parsing Offending resource: class path resource [applicationC

    这个错误是 org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration proble ...

  10. BUG管理工具——Mantis安装配置

    配置环境: CentOS6.5(所有操作在root用户下面操作) 1. 关闭防火墙, service iptables stop(防止防火墙捣乱,或者还得手动添加端口号的麻烦) 2. Disable ...