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

题面

有一个大小为\(n\)的集合\(S\)

问所有点权都在集合中,并且点权之和分别为\([0,m]\)的二叉树的个数。

\(n,m<=10^5\)

题解

设\(f(i)\)表示点权和为\(i\)的二叉树个数,\(c(i)\)是集合中数的生成函数,那么我们可以得到

\[f(n)=\sum_{i=1}^{n}c(i)\sum_{j=0}^{n-i}f(j)f(n-i-j)
\]

显然有\(f(0)=1\)

构造生成函数\(F(x)=\sum_{i=0}^{\infty}f(i)x^i,C(x)=\sum_{i=0}^{\infty}c(i)x^i\)。回顾递推式,后面的显然是\(F(x)*F(x)\),而如果设\(G(x)=F(x)*F(x)\)

那么,根据上面的式子\([x^n]F(n)=\sum_{i=0}^{n}c(i)[x^n]G(n-i)\)

所以,\(F(x)=G(x)*C(x)+1=F(x)*F(x)*C(x)+1\),要\(+1\)的原因是,如果只算卷积,我们会漏算\(f(0)=1\)。直接解方程就行了。

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

负号被舍去的原因是,生成函数的\(x\)没有实际意义,因此可以带入任何数,当带入\(x=0\)时,分母为\(0\),所以底下为正号。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 500000
#define MOD 998244353
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int n,m,inv2,d[MAX];
int fpow(int a,int b)
{
int s=1;
while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}
return s;
}
namespace NTT
{
int r[MAX],N,M,l;
int A[MAX],B[MAX];
void NTT(int *P,int n,int opt)
{
int N=1,l=0;for(N=1;N<n;N<<=1)++l;
for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
for(int i=1;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
for(int i=1;i<N;i<<=1)
{
int W=fpow(3,(MOD-1)/(i<<1));
for(int p=i<<1,j=0;j<N;j+=p)
{
int w=1;
for(int k=0;k<i;++k,w=1ll*w*W%MOD)
{
int X=P[j+k],Y=P[i+j+k]*1ll*w%MOD;
P[j+k]=(X+Y)%MOD;P[i+j+k]=(X-Y+MOD)%MOD;
}
}
}
if(opt==-1)
{
reverse(&P[1],&P[N]);
for(int i=0,inv=fpow(N,MOD-2);i<N;++i)P[i]=1ll*P[i]*inv%MOD;
}
}
}
int b[MAX];
int A[MAX],B[MAX],C[MAX],D[MAX],c[MAX];
void Inv(int *a,int *b,int len)
{
if(len==1){b[0]=fpow(a[0],MOD-2);return;}
Inv(a,b,len>>1);
for(int i=0;i<len;++i)A[i]=a[i],B[i]=b[i];
NTT::NTT(A,len<<1,1);NTT::NTT(B,len<<1,1);
for(int i=0;i<(len<<1);++i)A[i]=1ll*A[i]*B[i]%MOD*B[i]%MOD;
NTT::NTT(A,len<<1,-1);
for(int i=0;i<len;++i)b[i]=(b[i]+b[i])%MOD;
for(int i=0;i<len;++i)b[i]=(b[i]+MOD-A[i])%MOD;
for(int i=0;i<(len<<1);++i)A[i]=B[i]=0;
}
void Sqrt(int *a,int *b,int len)
{
if(len==1){b[0]=a[0];return;}
Sqrt(a,b,len>>1);
for(int i=0;i<=len;++i)C[i]=a[i];
Inv(b,D,len);
NTT::NTT(C,len<<1,1);NTT::NTT(D,len<<1,1);
for(int i=0;i<(len<<1);++i)D[i]=1ll*D[i]*C[i]%MOD;
NTT::NTT(D,len<<1,-1);
for(int i=0;i<len;++i)b[i]=1ll*(D[i]+b[i])%MOD*inv2%MOD;
for(int i=0;i<=(len<<1);++i)C[i]=D[i]=0;
}
int main()
{
n=read();m=read();inv2=fpow(2,MOD-2);
for(int i=1;i<=n;++i)++d[read()];
int N=1;while(N<=m)N<<=1;
for(int i=0;i<N;++i)d[i]=(-4*d[i]+MOD)%MOD;
++d[0];
Sqrt(d,c,N);
for(int i=0;i<N;++i)d[i]=0;
c[0]=(c[0]+1)%MOD;
Inv(c,d,N);
for(int i=0;i<=m;++i)d[i]=(d[i]+d[i])%MOD;
for(int i=1;i<=m;++i)printf("%d\n",d[i]);
return 0; }

【CF438E】The Child and Binary Tree(多项式运算,生成函数)的更多相关文章

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

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

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

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

  3. Codeforces 438E. The Child and Binary Tree 多项式,FFT

    原文链接www.cnblogs.com/zhouzhendong/p/CF438E.html 前言 没做过多项式题,来一道入门题试试刀. 题解 设 $a_i$ 表示节点权值和为 $i$ 的二叉树个数, ...

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

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

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

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

  6. 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( ...

  7. CF438E The Child and Binary Tree

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

  8. CF438E The Child and Binary Tree(生成函数,NTT)

    题目链接:洛谷 CF原网 题目大意:有 $n$ 个互不相同的正整数 $c_i$.问对于每一个 $1\le i\le m$,有多少个不同形态(考虑结构和点权)的二叉树满足每个点权都在 $c$ 中出现过, ...

  9. bzoj 3625(CF 438E)The Child and Binary Tree——多项式开方

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3625 http://codeforces.com/contest/438/problem/E ...

  10. Codeforces 438E The Child and Binary Tree [DP,生成函数,NTT]

    洛谷 Codeforces 思路 看到计数和\(998244353\),可以感觉到这是一个DP+生成函数+NTT的题. 设\(s_i\)表示\(i\)是否在集合中,\(A\)为\(s\)的生成函数,即 ...

随机推荐

  1. IBM X3650M4简单排错方法

    如果出问题了,首先看开机的那个地方的灯是否显示正常,有黄色的灯亮一般都不正常: 这种服务器带有一个错误指示板,只需要在电源开关那,如上图,把那个蓝色的按钮往里面按,就能把里面的一个板子抽出来,可以看到 ...

  2. 我们一起学习WCF 第七篇会话模式

    会话:就是客户端和服务端之间的谈话.比喻A和B去登陆网站,那么A用户登陆进去肯定显示A的用户详情,那么这就是A和服务器之间的交流.同样B用户登陆之后显示B的详情,这就表示这是B和服务器之间的交流. 如 ...

  3. Windows网络通信(二):socket异步编程

    简述 这里使用的API和同步编程的API是差不多的,只多了一个ioctlsocket和select函数.这里面涉及一个很重要的结构体fd_set.这里用到的API大部分都是windows和linux通 ...

  4. [CF1137]Museums Tour

    link \(\text{Description:}\) 一个国家有 \(n\) 个城市,\(m\) 条有向道路组成.在这个国家一个星期有 \(d\) 天,每个城市有一个博物馆. 有个旅行团在城市 \ ...

  5. python—退出ipython3的help()

    退出ipython3的help() 组合键:ctrl+z

  6. scrapy+selenium+chromedriver解析动态渲染页面

    背景:动态页面是页面是通过js代码渲染出来的,无法直接使用scrapy爬虫,这是就需要先把js代码转为静态的html,再用scrapy爬虫就可以解决 解决办法:增加SeleniumMiddleware ...

  7. mysql把一字段拆分为多行

    sql语句 select a.house_no as '房子',substring_index(substring_index(a.name,',',b.help_topic_id+1),',',-1 ...

  8. javascript中的取反再取反~~

    操作符~, 是按位取反的意思,表面上~~(取反再取反)没有意义,实际上在JS中可以将浮点数变成整数. <html> <script> var myArray = new Arr ...

  9. 过山车 HDU 2063 (二分图匹配裸题)

    Problem Description RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了.可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生 ...

  10. 【并查集】 不相交集合 - 并查集 教程(文章作者:Slyar)

    最近写了一个多星期的并查集,一瞬间贴出这么多解题报告,我想关于并查集的应用先告一段落吧,先总结一下. 在网上看到一篇关于并查集比较好的教程(姑且允许我这么说吧),不转过来是在可惜.献给爱学习的你 文章 ...