[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, ...
随机推荐
- [Java]hashCode的作用
一.如何理解hashCode的作用: 以java.lang.Object来理解,JVM每new一个Object,它都会将这个Object丢到一个Hash哈希表中去,这样的话,下次做Object的比较或 ...
- 洛谷P4238【模板】多项式求逆
洛谷P4238 多项式求逆:http://blog.miskcoo.com/2015/05/polynomial-inverse 注意:直接在点值表达下做$B(x) \equiv 2B'(x) - A ...
- curl_setopt 注意
最近碰到好多奇怪的BUG,今天就是一个例子. 我在用CURL调用麦考林的接口,在浏览器测试完全没问题,调用全都成功.但是用命令行执行PHP时,却一直不行,返回http code 302错误.百思不得其 ...
- AD中添加中文字符丝印的方法:
一 一般中文丝印: 用快捷键L打开层管理,在View options中勾选convert special 选项: 用快捷键P,S文本中输入你要的汉字,选中ture type,在select ture ...
- 配置本地和远程maven仓库
<mirrors><mirror> <id>alimaven</id> <name>aliyun maven</name> &l ...
- 《javascript设计模式》笔记之第十二章:装饰者模式
一.装饰者模式的作用 为函数或者对象的方法添加一些行为. 二.装饰者模式的原理 装饰者模式不是直接修改对象,而是以要修改的对象为基础,新建一个对象.不过这个新建的对象看起来就像在原对象的基础上 ...
- 前端开发如何做好SEO优化的工作
前端开发工程师不仅需要要跟视觉设计师.交互式设计师配合,完美还原设计图稿,编写兼容各大浏览器.加载速度快.用户体验好的页面.现在还需要跟SEO人员配合,调整页面的代码结构和标签. 一些成熟的平台,在开 ...
- 图解css3のborder-radius
早期制作圆角都是使用图片来实现.通过用1px 的水平线条来堆叠出圆角或者利用JavaScript等等方法,但是都是需要增加多个无意义的标签来实现,造成代码亢余.如今有了CSS3的圆角属性——borde ...
- 基于WebSocket和SpringBoot的群聊天室
引入 普通请求-响应方式:例如Servlet中HttpServletRequest和HttpServletResponse相互配合先接受请求.解析数据,再发出响应,处理完成后连接便断开了,没有数据的实 ...
- AJPFX浅析Java数组
数组(array)是相同类型变量的集合,可以使用共同的名字引用它.数组可被定义为任何类型,可以是一维或多维.数组中的一个特别要素是通过下标来访问它.数组提供了一种将有联系的信息分组的便利方法.注意:如 ...