题面

传送门

思路

首先,我们把这个输入的点的生成函数搞出来:

$C=\sum_{i=0}{lim}s_ixi$

其中$lim$为集合里面出现过的最大的数,$s_i$表示大小为$i$的数是否出现过

我们再设另外一个函数$F$,定义$F_k$表示总权值为$k$的二叉树个数

那么,一个二叉树显然可以通过两个子树(可以权值为0,也就是空子树)和一个节点构成

那么有如下求$F$的式子

$F_0=1$

$F_k=\sum_{i=0}^k s_i \sum_{j=0}^{k-i} F_j F_{k-i-j}$

显然这个式子是一个卷积的形式

我们把这个三个东西的卷积放到整个函数上来考虑(也就是把$F_kC_k$看做多项式的系数做卷积),可以得到:

$F=C\ast F\ast F +1$,这里的$\ast$是多项式乘法

由于多项式乘法和普通乘法一样满足各种定律之类的,所以我们可以解个一元二次方程

$C\ast F^2 - F + 1=0$

$F=\frac{1\pm \sqrt{1-4C}}{2C}$

先考虑上面是+的情况

此时${\lim_{x \to 0}}F(x)=+\infty$,舍去

再考虑-的情况

此时${\lim_{x \to 0}}F(x)=1$,OK

其实到这里就可以算了,一个多项式开方+多项式求逆就解决了

但是我们更进一步,再划一划这个式子,可以变成如下形式:

$F=\frac{2}{1+\sqrt{1-4C}}$

多项式开方+多项式求逆解决问题

Code:

这题超!级!卡!常!我这种人傻常数大的,只能参照爷稳稳的代码写一写了qwq

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<cmath>
#include<ctime>
#define ll long long
#define MOD 998244353
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,m,K;
ll A[600010],B[600010],C[600010],x[600010],y[600010];
int g=3,ginv,inv2,r[600010],lim,cnt;
ll qpow(ll a,ll b){
ll re=1;
while(b){
if(b&1) re=re*a%MOD;
a=a*a%MOD;b>>=1;
}
return re;
}
ll add(ll a,ll b){
a+=b;
return (a>=MOD)?a-MOD:a;
}
ll dec(ll a,ll b){
a-=b;
return (a<0)?a+MOD:a;
}
void ntt(ll *a,ll type){
int i,j,k;ll x,y,w,wn,inv,mid;
for(i=0;i<lim;i++) if(i<r[i]) swap(a[i],a[r[i]]);
for(mid=1;mid<lim;mid<<=1){
wn=qpow((type==1)?g:ginv,(MOD-1)/(mid<<1));
for(j=0;j<lim;j+=(mid<<1)){
w=1;
for(k=0;k<mid;k++,w=w*wn%MOD){
x=a[j+k];y=a[j+k+mid]*w%MOD;
a[j+k]=add(x,y);
a[j+k+mid]=dec(x,y);
}
}
}
if(~type) return;
inv=qpow(lim,MOD-2);
for(i=0;i<lim;i++) a[i]=a[i]*inv%MOD;
}
void getinv(ll *a,ll *b,int len,int lena){
if(len==1){b[0]=qpow(a[0],MOD-2);return;}
assert(len==((len>>1)<<1));
int i,mid=len>>1;
getinv(a,b,mid,lena);
lim=1;cnt=0;r[0]=0;
while(lim<=(len<<1)) lim<<=1,cnt++;
for(i=0;i<lim;i++) r[i]=((r[i>>1]>>1)|((i&1)<<(cnt-1))); for(i=0;i<len;i++) x[i]=a[i];
for(i=len;i<lim;i++) x[i]=0;
for(i=0;i<mid;i++) y[i]=b[i];
for(i=len;i<lim;i++) y[i]=0; ntt(x,1);ntt(y,1);
for(i=0;i<lim;i++) x[i]=y[i]*(2ll-y[i]*x[i]%MOD+MOD)%MOD;
ntt(x,-1);
for(i=0;i<len;i++) b[i]=x[i];
}
void getrt(ll *a,ll *b,int len){
if(len==1){b[0]=1;return;}
int i,mid=len>>1; getrt(a,b,mid);
memset(C,0,sizeof(C));getinv(b,C,len,len); lim=1;cnt=0;r[0]=0;
while(lim<=(len<<1)) lim<<=1,cnt++;
for(i=0;i<lim;i++) r[i]=((r[i>>1]>>1)|((i&1)<<(cnt-1))),x[i]=a[i];
for(i=len;i<lim;i++) x[i]=C[i]=b[i]=0; ntt(x,1);ntt(C,1);
for(i=0;i<lim;i++) x[i]=x[i]*C[i]%MOD;
ntt(x,-1); for(i=0;i<len;i++) b[i]=add(b[i],x[i])*inv2%MOD;
}
void init(){
ginv=qpow(g,MOD-2);
inv2=qpow(2,MOD-2);
}
int main(){
init();
n=read();m=read();int i,t1;A[0]=K=1;
for(i=1;i<=n;i++) t1=read(),A[t1]=dec(A[t1],4);
while(K<=m) K<<=1; getrt(A,B,K);
B[0]=add(B[0],1);
memset(C,0,sizeof(C));
getinv(B,C,K,K);
for(i=1;i<=m;i++) printf("%lld\n",(2*C[i]+MOD)%MOD);
}

[Codeforces438E][bzoj3625] 小朋友和二叉树 [多项式求逆+多项式开根]的更多相关文章

  1. FFT模板 生成函数 原根 多项式求逆 多项式开根

    FFT #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> ...

  2. 【BZOJ3625】【codeforces438E】小朋友和二叉树 生成函数+多项式求逆+多项式开根

    首先,我们构造一个函数$G(x)$,若存在$k∈C$,则$[x^k]G(x)=1$. 不妨设$F(x)$为最终答案的生成函数,则$[x^n]F(x)$即为权值为$n$的神犇二叉树个数. 不难推导出,$ ...

  3. 2019.01.01 bzoj3625:小朋友和二叉树(生成函数+多项式求逆+多项式开方)

    传送门 codeforces传送门codeforces传送门codeforces传送门 生成函数好题. 卡场差评至今未过 题意简述:nnn个点的二叉树,每个点的权值KaTeX parse error: ...

  4. bzoj 3625小朋友和二叉树 多项式求逆+多项式开根 好题

    题目大意 给定n种权值 给定m \(F_i表示权值和为i的二叉树个数\) 求\(F_1,F_2...F_m\) 分析 安利博客 \(F_d=F_L*F_R*C_{mid},L+mid+R=d\) \( ...

  5. NTT+多项式求逆+多项式开方(BZOJ3625)

    定义多项式$h(x)$的每一项系数$h_i$,为i在c[1]~c[n]中的出现次数. 定义多项式$f(x)$的每一项系数$f_i$,为权值为i的方案数. 通过简单的分析我们可以发现:$f(x)=\fr ...

  6. 【learning】多项式相关(求逆、开根、除法、取模)

    (首先要%miskcoo,这位dalao写的博客(这里)实在是太强啦qwq大部分多项式相关的知识都是从这位dalao博客里面学的,下面这篇东西是自己对其博客学习后的一些总结和想法,大部分是按照其博客里 ...

  7. 【BZOJ3456】轩辕朗的城市规划 无向连通图计数 CDQ分治 FFT 多项式求逆 多项式ln

    题解 分治FFT 设\(f_i\)为\(i\)个点组成的无向图个数,\(g_i\)为\(i\)个点组成的无向连通图个数 经过简单的推导(枚举\(1\)所在的连通块大小),有: \[ f_i=2^{\f ...

  8. bzoj 3456 城市规划——分治FFT / 多项式求逆 / 多项式求ln

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3456 分治FFT: 设 dp[ i ] 表示 i 个点时连通的方案数. 考虑算补集:连通的方 ...

  9. P6295-有标号 DAG 计数【多项式求逆,多项式ln】

    正题 题目链接:https://www.luogu.com.cn/problem/P6295 题目大意 求所有\(n\)个点的弱联通\(DAG\)数量. \(1\leq n\leq 10^5\) 解题 ...

随机推荐

  1. Objection, 一个轻量级的Objective-C依赖注入框架

    简介 项目主页:https://github.com/atomicobject/objection 实例下载: https://github.com/ios122/ios122 Objection 是 ...

  2. udp重发java实现

    最近在处理框架通讯方面的问题,通过积累的开发经验,其实在很多情况(尤其是实时大数据量),udp是占有很多优势的:不需要连接,只管发送,理论上要快很多; 另外在穿墙上占有很大优势: 但是最大的一个问题就 ...

  3. C++的队列和pair

    C++队列的成员函数: back()返回最后一个元素 empty()如果队列空则返回真 front()返回第一个元素 pop()删除第一个元素 push()在末尾加入一个元素 size()返回队列中元 ...

  4. 记一次FTP下载踩坑的故(shi)事(gu)

    下班前领导忽然要求我将客户的日志服务器上一些日志拷贝到测试服务器中,不过领导只提供给我FTP的连接方式,很明显就是要我用FTP方式去做啦 一般来说FTP批量下载也就上网随便找个脚本的事,但是却成了我疯 ...

  5. 【Mysql】给mysql配置远程登录

    grant all privileges on 库名.表名 to '用户名'@'IP地址' identified by '密码' with grant option; flush privileges ...

  6. rsync同步备份搭建

    Rsync 是 Unix/Linux 下的一款应用软 在平常的运维中进常要对一些数据进行备份,以防止意外的服务器故障导致不可避免的后果,tar,cp只能适应一些小范围backup,对于几T甚至几P的数 ...

  7. nodejs的http-server--web前端福利

    很多web前端在日常开发的时候可能会想常开发是谁. 不好意思,说错了. 很多web前端在日常开发的时候总是避免不了让所写页面在服务器环境下执行. 比如当你在用angularjs的route模块等等等. ...

  8. (转)想从事游戏开发,1 年内能精通 C++ 吗,还需要学习什么?

    本人大约从20多年前开始学习及使用C++,但仍未达到我认为「精通」的阶段,甚至对于C++11的各种新特性也未掌握.然而因为我是在读书时自学C++的,也是游戏程序员(原问题中提到题主想从事游戏开发),觉 ...

  9. python——PIL(图像处理库)

    PIL(Python Imaging Library,python图像处理库)提供了通用的图像处理功能,以及大量有用的基本图像操作,如图像缩放,裁剪,旋转,颜色转换等. 1.打开图像并显示 from ...

  10. [CodeForces948B]Primal Sport(数论)

    Description 题目链接 Solution 设f(x)为x的最大质因子 那么由题意易得\(X_1\)的范围在\([X_2-f(X_2)+1,X2]\) 同理\(X_0\)的范围在\([X_1- ...