题目描述:

bzoj

luogu

题解:

生成函数ntt。

显然这种二叉树应该暴力薅掉树根然后分裂成两棵子树。

所以$f(x)= \sum_{i \in c} \sum _{j=0}^{x-c} f(i)*f(x-i-j)$

这是个不好看的卷积。

所以我们再引入$c$的生成函数$G$,那么有$$F(x)=1+G(x)*F(x)*F(x)$$

注意常数项,因为正常$f(0)=1$但是$G(0)=0$,所以要人为配常数。

然后$F= \frac{1 \pm \sqrt{1-4G}} {2G} = \frac{2}{1 \pm \sqrt{1-4G}}$

还是因为系数,正负号只能取正。

bz严重卡常:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = ;
const int MOD = ;
const int inv_2 = ((MOD+)>>);
template<typename T>
inline void read(T&x)
{
T f = ,c = ;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){c=c*+ch-'';ch=getchar();}
x = f*c;
}
inline void Mod(unsigned int&x){if(x>=MOD)x-=MOD;}
inline unsigned int fastpow(unsigned int x,int y)
{
int ret = ;
while(y)
{
if(y&)ret=1ll*ret*x%MOD;
x=1ll*x*x%MOD;y>>=;
}
return ret;
}
int inv(const unsigned int x){return fastpow(x,MOD-);}
int to[N],lim,L,LL[N],n,m;
inline void init(const int len)
{
lim=LL[]=;
while(lim<=len)lim<<=,LL[lim<<]=LL[lim]+;
}
unsigned int W[N],INV;
inline void get_lim(const int len)
{
lim = len,L = LL[len];
for(register int i=;i<lim;++i)to[i]=((to[i>>]>>)|((i&)<<(L-)));
INV = inv(len);
for(register int i=;i<lim;i<<=)W[i]=fastpow(,(MOD-)/(i<<));
}
inline void ntt(unsigned int*a,const int len,const int k)
{
for(register int i=;i<len;++i)
if(i<to[i])swap(a[i],a[to[i]]);
for(register int i=;i<len;i<<=)
{
unsigned int w0 = W[i];
for(register int j=;j<len;j+=(i<<))
{
unsigned int w = ;
for(register int o=;o<i;++o,w=1ll*w*w0%MOD)
{
unsigned int w1 = a[j+o],w2 = 1ll*a[j+o+i]*w%MOD;
Mod(a[j+o]=w1+w2);
Mod(a[j+o+i]=w1+MOD-w2);
}
}
}
if(k==-)
{
for(register int i=;i<len>>;++i)swap(a[i],a[len-i]);
for(register int i=;i<len;++i)a[i]=1ll*a[i]*INV%MOD;
}
}
unsigned int a[N],b[N],c[N];
void mul(unsigned int*F,unsigned int*G,unsigned int*H,const int len)
{
get_lim(len<<);
for(register int i=;i<lim;++i)a[i]=b[i]=;
for(register int i=;i<len;++i)a[i]=F[i],b[i]=G[i];
ntt(a,lim,),ntt(b,lim,);
for(register int i=;i<lim;++i)c[i]=1ll*a[i]*b[i]%MOD;
ntt(c,lim,-);
for(register int i=;i<lim;++i)H[i]=c[i];
}
unsigned int T[N];
void get_inv(unsigned int*F,unsigned int*G,const int len)
{
if(len==){G[]=inv(F[]),G[]=;return ;}
get_inv(F,G,len>>);
get_lim(len<<);for(register int i=;i<lim;++i)a[i]=b[i]=;
for(register int i=;i<len;++i)a[i]=F[i];for(register int i=;i<(len>>);++i)b[i]=G[i];
ntt(a,lim,),ntt(b,lim,);for(register int i=;i<lim;++i)c[i]=1ll*a[i]*b[i]%MOD*b[i]%MOD;ntt(c,lim,-);
for(register int i=;i<len;++i)G[i]=(2ll*G[i]+MOD-c[i])%MOD,G[i+len]=;
}
unsigned int H[N];
void get_sqrt(unsigned int*F,unsigned int*G,const int len)
{
if(len==){G[]=;return ;}
get_sqrt(F,G,len>>);get_inv(G,H,len);
mul(G,G,T,len);for(register int i=;i<len;++i)T[i]=1ll*(T[i]+F[i])*inv_2%MOD;
mul(H,T,G,len);for(register int i=len;i<(len<<);++i)G[i]=;
}
unsigned int F[N],G[N],S[N];
int main()
{
// freopen("tt.in","r",stdin);
read(n),read(m);
init(m);int c,mx = lim;
for(register int i=;i<=n;++i)
read(c),G[c]=MOD-;
G[]++;
get_sqrt(G,S,mx);
S[]++;
for(register int i=;i<mx;++i)S[i]=1ll*S[i]*inv_2%MOD;
get_inv(S,F,mx);
for(register int i=;i<=m;++i)
printf("%u\n",F[i]);
return ;
}

[Codeforces Round #250]小朋友和二叉树的更多相关文章

  1. BZOJ 3625: [Codeforces Round #250]小朋友和二叉树

    3625: [Codeforces Round #250]小朋友和二叉树 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 13 ...

  2. BZOJ3625: [Codeforces Round #250]小朋友和二叉树

    Description 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树.考虑一个含有n个互异正整数的序列c[1],c[2],...,c[n].如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合{ ...

  3. BZOJ3625 [Codeforces Round #250]小朋友和二叉树(生成函数+多项式开根)

    设f(n)为权值为n的神犇二叉树个数.考虑如何递推求这个东西. 套路地枚举根节点的左右子树.则f(n)=Σf(i)f(n-i-cj),cj即根的权值.卷积的形式,cj也可以通过卷上一个多项式枚举.可以 ...

  4. BZOJ 3625 [Codeforces Round #250]小朋友和二叉树 ——NTT 多项式求逆 多项式开根

    生成函数又有奇妙的性质. $F(x)=C(x)*F(x)*F(x)+1$ 然后大力解方程,得到一个带根号的式子. 多项式开根有解只与常数项有关. 发现两个解只有一个是成立的. 然后多项式开根.求逆. ...

  5. bzoj 3625: [Codeforces Round #250]小朋友和二叉树【NTT+多项式开根求逆】

    参考:https://www.cnblogs.com/2016gdgzoi509/p/8999460.html 列出生成函数方程,g(x)是价值x的个数 \[ f(x)=g(x)*f^2(x)+1 \ ...

  6. [BZOJ3625][Codeforces Round #250]小朋友和二叉树 多项式开根+求逆

    https://www.lydsy.com/JudgeOnline/problem.php?id=3625 愉快地列式子.设\(F[i]\)表示权值为\(i\) 的子树的方案数,\(A[i]\)为\( ...

  7. Codeforces Round#250 D. The Child and Zoo(并差集)

    题目链接:http://codeforces.com/problemset/problem/437/D 思路:并差集应用,先对所有的边从大到小排序,然后枚举边的时候,如果某条边的两个顶点不在同一个集合 ...

  8. Codeforces Round #250 (Div. 2)A(英语学习)

    链接:http://codeforces.com/contest/437/problem/A A. The Child and Homework time limit per test 1 secon ...

  9. Codeforces Round #250 (Div. 1) D. The Child and Sequence (线段树)

    题目链接:http://codeforces.com/problemset/problem/438/D 给你n个数,m个操作,1操作是查询l到r之间的和,2操作是将l到r之间大于等于x的数xor于x, ...

随机推荐

  1. java基础第九篇之final和内部类等

    final关键字:final:最终,终极 final:作用:修饰类,变量,方法.成员变量的访问 1.final修饰变量: final修饰局部变量: 把这个局部变量 变成一个厂里,这个厂里只能被赋值一次 ...

  2. 2016 CCPC-Final

    A.The Third Cup is Free #include <bits/stdc++.h> using namespace std; typedef long long ll; in ...

  3. 页面出现滚动条时,body里面的内容不能自动居中?

    弹窗后允许页面滚动 这种方式通常使用 position: absolute; ,可以看看我做的这个 Demo.主要用来应对弹窗内容很大很多的情况,超过了屏幕的宽高需要产生滚动条来方便浏览者查看.有一些 ...

  4. BZOJ 1899&&luogu P2577: [Zjoi2004]Lunch 午餐 贪心+DP

    贪它,再大力DP(话说觉得此题简单的真的是大佬QAQ)我想了两天...QWQ 贪心:吃饭慢的先打饭(不太会证...) DP:f[i][j]表示前i个人,在1号窗口打饭的总时间时j,的最短时间 确定i的 ...

  5. 命令行 IRC 客户端 irssi 的基本操作

    登录与退出 启动 irssi $ irssi 登陆 IRC 服务器/connect server port 修改昵称/nick nickname 直接带昵称登录指定的服务器$ irssi -c [se ...

  6. NET高性能IO

    System.IO.Pipelines: .NET高性能IO https://www.cnblogs.com/xxfy1/p/9290235.html System.IO.Pipelines是一个新的 ...

  7. 规则引擎.Net Core

    .Net Core 环境下构建强大且易用的规则引擎 https://www.cnblogs.com/chenug/p/9160397.html 本文源码: https://github.com/jon ...

  8. NET Everywhere

    NET Everywhere 8月份已经发布了.NET Core 2.0, 大会Keynote 一开始花了大量的篇幅回顾.NET Core 2.0的发布,社区的参与度已经非常高.大会的主题是.NET ...

  9. HDU 1024 A - Max Sum Plus Plus DP + 滚动数组

    http://acm.hdu.edu.cn/showproblem.php?pid=1024 刚开始的时候没看懂题目,以为一定要把那n个数字分成m对,然后求m对中和值最大的那对 但是不是,题目说的只是 ...

  10. (转)linux dumpe2fs命令

    linux dumpe2fs命令 命令名称 dumpe2fs - 显示ext2/ext3/ext4文件系统信息. dumpe2fs命令语法 dumpe2fs [ -bfhixV ] [ -o supe ...