传送门

可以……这很多项式开根模板……而且也完全不知道大佬们怎么把这题的式子推出来的……

首先,这题需要多项式开根和多项式求逆。多项式求逆看这里->这里,这里讲一讲多项式开根

多项式开方:已知多项式$B$,求多项式$A$满足$A^2\equiv B\pmod{x^n}$(和多项式求逆一样这里需要取模,否则$A$可能会有无数项)

假设我们已经求出$A'^2\equiv B\pmod{x^n}$,考虑如何计算出$A^2\equiv B\pmod{x^{2n}}$

首先肯定存在$A^2\equiv B\pmod{x^n}$

然后两式相减$$A'^2-A^2\equiv 0\pmod{x^n}$$

$$(A'-A)(A'+A)\equiv 0\pmod{x^n}$$

我们假设$A'-A\equiv 0\pmod{x^n}$,然后两边平方$$A'^2-2A'A+A^2\equiv 0\pmod{x^{2n}}$$

(关于平方之后模数变化的原因可以看我多项式求逆那篇文章,里面有写)

又因为$A^2\equiv B\pmod{x^{2n}}$,代入得$$A'^2-2A'A+B\equiv 0\pmod{x^{2n}}$$

$$A\equiv\frac{A'^2+B}{2A'}\pmod{x^{2n}}$$

那么这个只要递归计算就可以了

然后多项式开方就讲到这里

下面说一下本题的做法

首先,我也不知道怎么想到的构造出生成函数,$C=\sum_{i=1}^{lim}s_ix^i$,其中$s_i$表示$i$是否在集合中出现过,然后再设一个$F_k$表示权值为$k$时的答案

因为一棵二叉树可以由根节点,左右子树构成(左右子树可以是空的)

那么存在如下关系$$F_k=\sum_{i=0}^ks_i\sum_{j=0}^{k-i}F_jF_{k-i-j}$$

然后我也不知道怎么看出来的发现这是一个卷积的形式,即$$F=1+C*F*F$$(这里$*$是多项式乘法)(这里$1$是加上去的常数项,因为有$F_0=1$,即空树)

把它看做一个一元二次方程求解,得$$F=\frac{1\pm \sqrt{1-4C}}{2C}=\frac{2}{1\pm\sqrt{1-4C}}$$

然后因为$F_0=1,C_0=0$,所以符号取正,即$$F=\frac{2}{1+\sqrt{1-4C}}$$

那么把多项式开根和多项式求逆的板子带进去就好了

 //minamoto
#include<iostream>
#include<cstdio>
#include<algorithm>
#define swap(x,y) (x^=y,y^=x,x^=y)
#define mul(x,y) (1ll*x*y%P)
#define add(x,y) (x+y>=P?x+y-P:x+y)
#define dec(x,y) (x-y<0?x-y+P:x-y)
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int K=-,Z;
inline void Ot(){fwrite(sr,,K+,stdout),K=-;}
inline void print(int x){
if(K><<)Ot();if(x<)sr[++K]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++K]=z[Z],--Z);sr[++K]='\n';
}
const int N=,P=,G=,inv2=;
inline int ksm(int a,int b){
int res=;
while(b){
if(b&) res=mul(res,a);
a=mul(a,a),b>>=;
}
return res;
}
int n,m,r[N],A[N],B[N],C[N],D[N],O[N],d[N],c[N];
void NTT(int *A,int type,int len){
int limit=,l=;
while(limit<len) limit<<=,++l;
for(int i=;i<limit;++i)
r[i]=(r[i>>]>>)|((i&)<<(l-));
for(int i=;i<limit;++i)
if(i<r[i]) swap(A[i],A[r[i]]);
for(int mid=;mid<limit;mid<<=){
int R=mid<<,Wn=ksm(G,(P-)/R);O[]=;
for(int j=;j<mid;++j) O[j]=mul(O[j-],Wn);
for(int j=;j<limit;j+=R){
for(int k=;k<mid;++k){
int x=A[j+k],y=mul(O[k],A[j+k+mid]);
A[j+k]=add(x,y),A[j+k+mid]=dec(x,y);
}
}
}
if(type==-){
reverse(A+,A+limit);
for(int i=,inv=ksm(limit,P-);i<limit;++i)
A[i]=mul(A[i],inv);
}
}
void Inv(int *a,int *b,int len){
if(len==) return (void)(b[]=ksm(a[],P-));
Inv(a,b,len>>);
for(int i=;i<len;++i) A[i]=a[i],B[i]=b[i];
NTT(A,,len<<),NTT(B,,len<<);
for(int i=,l=(len<<);i<l;++i) A[i]=mul(mul(A[i],B[i]),B[i]);
NTT(A,-,len<<);
for(int i=;i<len;++i) b[i]=dec(1ll*(b[i]<<)%P,A[i]);
for(int i=,l=(len<<);i<l;++i) A[i]=B[i]=;
}
void Sqrt(int *a,int *b,int len){
if(len==) return (void)(b[]=a[]);
Sqrt(a,b,len>>);
for(int i=;i<len;++i) C[i]=a[i];
Inv(b,D,len);
NTT(C,,len<<),NTT(D,,len<<);
for(int i=,l=len<<;i<l;++i) D[i]=mul(D[i],C[i]);
NTT(D,-,len<<);
for(int i=;i<len;++i) b[i]=mul(add(b[i],D[i]),inv2);
for(int i=,l=(len<<);i<l;++i) C[i]=D[i]=;
}
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read();
for(int i=,x;i<=n;++i) x=read(),++d[x];
int len;for(len=;len<=m;len<<=);
for(int i=;i<len;++i) d[i]=(-*d[i]+P)%P;
++d[];
Sqrt(d,c,len);
for(int i=;i<len;++i) d[i]=;
c[]=add(c[],);
Inv(c,d,len);
for(int i=;i<=m;++i) d[i]=add(d[i],d[i]);
for(int i=;i<=m;++i) print(d[i]);
Ot();
return ;
}

CF438E The Child and Binary Tree(生成函数+多项式开根+多项式求逆)的更多相关文章

  1. [BZOJ3625][CF438E]小朋友和二叉树 (多项式开根,求逆)

    题面 题解 设多项式的第a项为权值和为a的二叉树个数,多项式的第a项表示是否为真,即 则,所以F是三个多项式的卷积,其中包括自己: ,1是F的常数项,即. 我们发现这是一个一元二次方程,可以求出,因为 ...

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

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

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

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

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

  5. 【BZOJ3625】【CF438E】小朋友和二叉树 NTT 生成函数 多项式开根 多项式求逆

    题目大意 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\ldots ,c_n\).如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合\(\{c_1,c_2,\ldots ,c_n\ ...

  6. [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)

    [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...

  7. Codeforces 438E The Child and Binary Tree - 生成函数 - 多项式

    题目传送门 传送点I 传送点II 传送点III 题目大意 每个点的权值$c\in {c_{1}, c_{2}, \cdots, c_{n}}$,问对于每个$1\leqslant s\leqslant ...

  8. CF438E The Child and Binary Tree

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

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

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

随机推荐

  1. Java面向对象编程(一)

    由于常常将Java和C++面向对象编程的原则搞乱,所以这次把相关要点分别总结一下,本文主要总结Java面向对象编程. 面向对象编程的三大特性是:继承性(inheritance), 多态性(polymo ...

  2. jquery根据(遍历)html()的内容/根据子元素的内容(元素文本)来选择(查询),在子元素前加入元素

    <ul> <li>First</li> <li>second</li> <li>third</li> </ul ...

  3. Jquery AJAX如何使用Promise/Deferred实现顺序执行?

    有的时候有我有N个AJAX请求,第下个请求可能要依赖上个请求的返回值, 可以用 $.ajax("test1.php").then(function(data) { // data ...

  4. 【LeetCode】Search in Rotated Sorted Array II(转)

    原文链接 http://oj.leetcode.com/problems/search-in-rotated-sorted-array-ii/ http://blog.csdn.net/linhuan ...

  5. HTML5 Canvas 时钟

    1. [图片] QQ截图20120712130049.png ​2. [代码][HTML]代码 <!DOCTYPE html><html lang="en" &g ...

  6. WebRTC GitHub repo developer's guide

    WebRTC GitHub repo developer's guide https://github.com/LingyuCoder/SkyRTC-demo  WebRTC GitHub repo ...

  7. 自适应布局all样式

    /*css document*/@charset "utf-8"*{-webkit-tap-highlight-color:rgba(0,0,0,0); padding:0; ma ...

  8. Python: PS滤镜--径向模糊

    本文用 Python 实现 PS 滤镜中的径向模糊特效,具体的算法原理和效果可以参考之前的博客: http://blog.csdn.net/matrix_space/article/details/3 ...

  9. 【CQ18高一暑假前挑战赛3】标程

    [A:LCM] #include<bits/stdc++.h> using namespace std; #define ll long long int main() { ll a,b, ...

  10. 阻止Eclipse一直building workspace

    Eclipse 一直不停 building workspace完美解决总结 一.产生这个问题的原因多种 1.自动升级 2.未正确关闭 3.maven下载lib挂起 等.. 二.解决总结 (1).解决方 ...