题目描述:

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. 译—— a tale of viewport2

    这一页我们将讨论移动浏览器.如果您对移动设备完全陌生,我建议您首先阅读第一部分关于桌面浏览器的内容,以便在熟悉的环境中做好准备. 移动浏览器的问题 移动浏览器和桌面浏览器比较,最明显的差异是屏幕大小. ...

  2. path不相等的子集,父级

    SELECT a.path,b.path from comm_department_temp a INNER JOIN comm_department_temp b on a.id=b.parent_ ...

  3. 网站前端开发--css篇

    Ⅰ 全局:global.css 全局样式为全站公用,为页面样式基础,页面中必须包含. 结构:layout.css 页面结构类型复杂,并且公用类型较多时使用.多用在首页级页面和产品类页面中. 私有:st ...

  4. selenium基础操作

    selenium 1.打开和关闭网页 #!/usr/bin/env python # -*- coding:utf-8 -*- from selenium import webdriver drive ...

  5. Codeforces 1114F(欧拉函数、线段树)

    AC通道 要点 欧拉函数对于素数有一些性质,考虑将输入数据唯一分解后进行素数下的处理. 对于素数\(p\)有:\(\phi(p^k)=p^{k-1}*(p-1)=p^k*\frac{p-1}{p}\) ...

  6. Batch梯度下降

    1.之前讲到随机梯度下降法(SGD),如果每次将batch个样本输入给模型,并更新一次,那么就成了batch梯度下降了. 2.batch梯度下降显然能够提高算法效率,同时相对于一个样本,batch个样 ...

  7. windows 安装 jdk1.8并配置环境变量

    1.查看电脑环境 我的电脑--右键--属性 2.下载jdk1.8 网址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-do ...

  8. C# 加密、解密函数

    #region ========加密======== /// <summary> /// 加密 /// </summary> /// <param name=" ...

  9. webpack.config.js====entry入口文件的配置

    1.  一般是采用对象语法: entry: { index: './src/default/js/index.js' }, https://webpack.css88.com/concepts/ent ...

  10. SQL基本语法总结

    #创建数据库 DROP DATABASE IF EXISTS 数据库名; CREATE DATABASE 数据库名; #展示所有的数据库: SHOW DATABASES; #查看某个数据库的定义信息: ...