Description

给定一个整数集合 \(c\),对于每个 \(i\in[1,m]\),求有多少种不同的带点权的二叉树使得这棵树点权和为 \(i\) 并且顶点的点权全部在集合 \(c\) 中。\(m\leq 10^5\)。

Solution

设 \(f[i]\) 为点权为 \(i\) 的二叉树的方案, \(c[i]\) 表示 \(i\) 是否在集合 \(c\) 中。

所以 \(f[i]=\sum\limits_{j=1}^{i} c[j]\cdot\sum\limits_{p=0}^{i-j}f[p]\cdot \sum\limits_{k=0}^{i-j-p}f[k],f[0]=1\)

发现这是个卷积形式,也就是说 \(f[i+j+k]=c[i]\cdot f[j]\cdot f[k]\),即 \(f=c\times f\times f\)。

解一下方程,\(f=\frac{1\pm \sqrt{1-4c}}{2c}\)

然而 \(c\) 的常数项为 \(0\),所以不能求逆。尝试分子有理化解得 \(f=\frac2{1\pm\sqrt{1-4c}}\)

当 \(x=0\) 时,\(c=0,f=1\),所以分母只能取正号。

求逆+开根即可。

Code

#include<bits/stdc++.h>
using std::min;
using std::max;
using std::swap;
using std::vector;
typedef double db;
typedef long long ll;
#define pb(A) push_back(A)
#define pii std::pair<int,int>
#define all(A) A.begin(),A.end()
#define mp(A,B) std::make_pair(A,B)
const int N=4e5+5;
const int mod=998244353;
#define inv(x) ksm(x,mod-2) int lim,rev[N],f[N];
int n,m,tmpa[N],c[N];
int a[N],b[N],tmpb[N]; int ksm(int a,int b,int ans=1){
while(b){
if(b&1) ans=1ll*ans*a%mod;
a=1ll*a*a%mod;b>>=1;
} return ans;
} void ntt(int *f,int opt){
for(int i=0;i<lim;i++) if(i<rev[i]) swap(f[i],f[rev[i]]);
for(int mid=1;mid<lim;mid<<=1){
int tmp=ksm(3,(mod-1)/(mid<<1));
if(opt<0) tmp=inv(tmp);
for(int R=mid<<1,j=0;j<lim;j+=R){
int w=1;
for(int k=0;k<mid;k++,w=1ll*w*tmp%mod){
int x=f[j+k],y=1ll*w*f[j+k+mid]%mod;
f[j+k]=(x+y)%mod,f[j+k+mid]=(mod+x-y)%mod;
}
}
} if(opt<0)
for(int in=inv(lim),i=0;i<lim;i++) f[i]=1ll*f[i]*in%mod;
} void get(int n){
lim=1;while(lim<=n) lim<<=1;
for(int i=1;i<lim;i++) rev[i]=(rev[i>>1]>>1)|(i&1?lim>>1:0);
} void solveinv(int len,int *a,int *b){
if(len==1) return b[0]=inv(a[0]),void();
solveinv(len>>1,a,b);
get(len);
for(int i=0;i<len;i++) tmpa[i]=a[i];
ntt(tmpa,1),ntt(b,1);
for(int i=0;i<lim;i++) b[i]=1ll*b[i]*(2ll-1ll*tmpa[i]*b[i]%mod+mod)%mod;
ntt(b,-1);
for(int i=len;i<lim;i++) b[i]=0;
for(int i=0;i<lim;i++) tmpa[i]=0;
} void solvesqr(int len,int *a,int *b){
if(len==1) return b[0]=1,void();
solvesqr(len>>1,a,b);
solveinv(len,b,tmpb);
get(len);
for(int i=0;i<len;i++) tmpa[i]=a[i];
ntt(tmpb,1),ntt(tmpa,1);
for(int i=0;i<lim;i++) tmpa[i]=1ll*tmpa[i]*tmpb[i]%mod;
ntt(tmpa,-1);
for(int i=0,inv2=mod+1>>1;i<lim;i++) b[i]=1ll*(tmpa[i]+b[i])%mod*inv2%mod;
for(int i=len;i<lim;i++) b[i]=0;
for(int i=0;i<lim;i++) tmpa[i]=tmpb[i]=0;
} int getint(){
int X=0,w=0;char ch=getchar();
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while( isdigit(ch))X=X*10+ch-48,ch=getchar();
if(w) return -X;return X;
} signed main(){
n=getint(),m=getint();
for(int i=1;i<=n;i++){
int x=getint();
a[x]=1;
}
for(int i=1;i<=m;i++) if(a[i]) a[i]=mod-4;
get(m);a[0]=1;solvesqr(lim,a,b);
get(m);b[0]++;solveinv(lim,b,c);
for(int i=1;i<=m;i++) printf("%lld\n",2ll*c[i]%mod);
return 0;
}

[CF438E] 小朋友和二叉树的更多相关文章

  1. [BZOJ3625][CF438E]小朋友和二叉树

    题面 Description 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树. 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\ldots,c_n\).如果一棵带点权的有根二叉树满足其 ...

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

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

  3. BZOJ3625 CF438E 小朋友与二叉树

    心态崩了 不放传送门了 辣鸡bz 还是正经一点写一下题解= = 就是显然我们可以把权值写成生成函数形式g(0/1序列)来表示权值是否出现 然后f来表示总的方案数 可以列出 分别枚举左右子树和空树的情况 ...

  4. 【CF438E】小朋友和二叉树 解题报告

    [CF438E]小朋友和二叉树 Description ​ 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树. ​ 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\dots,c_n\). ...

  5. 【BZOJ3625/CF438E】小朋友和二叉树(多项式求逆,多项式开方)

    [BZOJ3625/CF438E]小朋友和二叉树(多项式求逆,多项式开方) 题面 BZOJ CodeForces 大致题意: 对于每个数出现的次数对应的多项式\(A(x)\) 求\[f(x)=\fra ...

  6. 【bzoj3625】【xsy1729】小朋友和二叉树

    [bzoj3625]小朋友与二叉树 题意 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树. 考虑一个含有n个互异正整数的序列c[1],c[2],...,c[n].如果一棵带点权的有根二叉树满足其所有 ...

  7. BZOJ 3625: [Codeforces Round #250]小朋友和二叉树

    3625: [Codeforces Round #250]小朋友和二叉树 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 13 ...

  8. 「BZOJ 3645」小朋友与二叉树

    「BZOJ 3645」小朋友与二叉树 解题思路 令 \(G(x)\) 为关于可选大小集合的生成函数,即 \[ G(x)=\sum[i\in c ] x^i \] 令 \(F(x)\) 第 \(n\) ...

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

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

随机推荐

  1. CMD命令启动和关闭SQL服务

    1.开启:net start mssqlserver 2.关闭:net stop mssqlserver

  2. jdbc随笔

    通过jdbc连接数据库的基本步骤:  导入jar包驱动类  jdbc语法:jdbc:子协议:厂商内容  对于mysql而言:jdbc:mysql://主机地址:端口号/库名               ...

  3. python模块:datetime

    # Stubs for datetime # NOTE: These are incomplete! import sys from typing import Optional, SupportsA ...

  4. 【转】comparable Interface

    作者:gnuhpc 出处:http://www.cnblogs.com/gnuhpc/ 1.什么是Comparable接口 此接口强行对实现它的每个类的对象进行整体排序.此排序被称为该类的自然排序 , ...

  5. Wordpress“固定链接”页面出现404原因及解决方法

    编辑配置文件:/etc/apache2/apache2.conf(非常靠后的位置),将里面的AllowOverride选项由None设置为All. <Directory /> Option ...

  6. JS图片验证码

    !(function(window, document) { var size = 5;//设置验证码长度 function GVerify(options) { //创建一个图形验证码对象,接收op ...

  7. [solution] JZOJ-5795 词典

    [solution]JZOJ-5795 词典 题面 Description 小C有$n$个字符串$T_1 T_n$,给出$m$个询问 第$i$个询问给出一个字符串$S_i$,对于每个询问,我们可以得到 ...

  8. elasticsearch之hello(spring data整合)

    1.书写pom.xml文件 <dependencies> <dependency> <groupId>org.springframework.data</gr ...

  9. go的数据库操作mysql

    go get github.com/go-sql-driver/mysql package main; import ( "database/sql" _ "github ...

  10. 卷积(转自wiki百科)

    维基百科,自由的百科全书 图示两个方形脉冲波的卷积.其中函数 "g" 首先对  反射,接着平移 "t" ,成为  .那么重叠部份的面积就相当于 "t& ...