[Codeforces Round #250]小朋友和二叉树
题目描述:
题解:
生成函数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]小朋友和二叉树的更多相关文章
- BZOJ 3625: [Codeforces Round #250]小朋友和二叉树
3625: [Codeforces Round #250]小朋友和二叉树 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 304 Solved: 13 ...
- BZOJ3625: [Codeforces Round #250]小朋友和二叉树
Description 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树.考虑一个含有n个互异正整数的序列c[1],c[2],...,c[n].如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合{ ...
- BZOJ3625 [Codeforces Round #250]小朋友和二叉树(生成函数+多项式开根)
设f(n)为权值为n的神犇二叉树个数.考虑如何递推求这个东西. 套路地枚举根节点的左右子树.则f(n)=Σf(i)f(n-i-cj),cj即根的权值.卷积的形式,cj也可以通过卷上一个多项式枚举.可以 ...
- BZOJ 3625 [Codeforces Round #250]小朋友和二叉树 ——NTT 多项式求逆 多项式开根
生成函数又有奇妙的性质. $F(x)=C(x)*F(x)*F(x)+1$ 然后大力解方程,得到一个带根号的式子. 多项式开根有解只与常数项有关. 发现两个解只有一个是成立的. 然后多项式开根.求逆. ...
- 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 \ ...
- [BZOJ3625][Codeforces Round #250]小朋友和二叉树 多项式开根+求逆
https://www.lydsy.com/JudgeOnline/problem.php?id=3625 愉快地列式子.设\(F[i]\)表示权值为\(i\) 的子树的方案数,\(A[i]\)为\( ...
- Codeforces Round#250 D. The Child and Zoo(并差集)
题目链接:http://codeforces.com/problemset/problem/437/D 思路:并差集应用,先对所有的边从大到小排序,然后枚举边的时候,如果某条边的两个顶点不在同一个集合 ...
- Codeforces Round #250 (Div. 2)A(英语学习)
链接:http://codeforces.com/contest/437/problem/A A. The Child and Homework time limit per test 1 secon ...
- 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, ...
随机推荐
- redis单机上部署集群
一.安装单机redis redis的安装:版本至少是3.2.8及其以上,这里以3.2.8版本为例说明 1.安装redis wget http://download.redis.io/releases ...
- 求n位水仙花数
求n位水仙花数 A.两个关键 1.n位水仙花数的范围是什么? n位水仙花数的范围是[10n-1,10n) 2.如何判断是否为水仙花数 核心操作: 2-1.如何得到每一位? A.核心思想 对得到的数进行 ...
- eclipse中windows下的preferences左栏没有tomcat?
是因为缺少eclipse for tomcat 插件,到http://www.eclipsetotale.com/tomcatPlugin.html此网站下载,我的eclipse版本是4.4版本的,所 ...
- JS高级学习历程-17
[正则案例] 1 匹配手机号码
- HDU-2767-ProvingEquivalences
链接:https://vjudge.net/problem/HDU-2767 题意: 给一个图,求最少需要几条边将其连成一个强连通图 思路: tarjan,缩点,考虑缩点后的图,出度为0的点和入度为0 ...
- Net Core下通过Proxy 模式
Net Core下通过Proxy 模式 NET Core下的WCF客户端也是开源的,这次发布.NET Core 2.0,同时也发布了 WCF for .NET Core 2.0.0, 本文介绍在.NE ...
- c++笔记3
一基本语法: 1.1 字符串:支持标准C的 const char* pch=0/"";//不指向任何对象和指向空字符串.C++提供的string类可提供字符串的所有操作,最好是融合 ...
- SpringMVC对HTTP报文体的处理
客户端和服务端HTTP报文传递消息,而HTTP报文包含报文头和报文体.通常,解析请求参数以及返回页面都不需要我们关心HTTP报文体的读取和生成过程.但在某些特定场景下需要直接到请求报文中读取报文体, ...
- jsp-简单的猜数小游戏
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"% ...
- java核心技术 - 17个重要的知识点
1.Java中没有多继承,而是用接口来代替多继承 2.运行一个已经编译的程序时,Java解释器总是从指定类的main方法中的代码开始执行,因此,执行代码中必须有一个main函数. 3.Java是典型的 ...