CF438E The Child and Binary Tree
思路
设F(x)的第x项系数为权值和为x的答案
题目中要求权值必须在集合中出现,这个不好处理,考虑再设一个C,C的第x项如果是1代表x出现在值域里,如果是0,代表x没有出现在值域里,然后由于二叉树可以分别对左右子树处理,所以
\]
\]
可以看出这是一个卷积的形式
\]
然后解一个一元二次方程
\]
因为\(C_0=0\),\(F_0=1\),所以去掉负号
然后上多项式求逆和多项式开方即可
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
const int MAXN = 300000;
const int MOD = 998244353;
const int G = 3;
const int invG = 332748118;
struct Poly{
int t,data[MAXN];
Poly(){};
};
int pow(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(Poly &a,int opt,int n){
int lim=0;
while((1<<(lim))<n){
lim++;
}
n=(1<<lim);
for(int i=0;i<n;i++){
int t=0;
for(int j=0;j<lim;j++)
if((i>>j)&1)
t|=(1<<(lim-j-1));
if(i<t)
swap(a.data[i],a.data[t]);
}
for(int i=2;i<=n;i<<=1){
int len=i/2;
int tmp=pow((opt)?G:invG,(MOD-1)/i);
for(int j=0;j<n;j+=i){
int arr=1;
for(int k=j;k<j+len;k++){
int t=(1LL*a.data[k+len]*arr)%MOD;
a.data[k+len]=(1LL*a.data[k]-t+MOD)%MOD;
a.data[k]=(1LL*a.data[k]+t)%MOD;
arr=(1LL*arr*tmp)%MOD;
}
}
}
if(!opt){
int invN = pow(n,MOD-2);
for(int i=0;i<n;i++){
a.data[i]=(1LL*a.data[i]*invN)%MOD;
}
}
}
void save(Poly &a,int top){
for(int i=top+1;i<=a.t;i++)
a.data[i]=0;
a.t=top;
}
void mul(Poly &a,Poly b){//a=a*b
int num=a.t+b.t,lim=0;
while((1<<lim)<=(num+2))
lim++;
lim=(1<<lim);
NTT(a,1,lim);
NTT(b,1,lim);
for(int i=0;i<lim;i++)
a.data[i]=(1LL*a.data[i]*b.data[i])%MOD;
NTT(a,0,lim);
a.t=num;
for(int i=num+1;i<lim;i++)
a.data[i]=0;
}
void Inv(Poly a,Poly &b,int dep,int &midlen){
if(dep==1){
b.data[0]=pow(a.data[0],MOD-2);
b.t=dep-1;
return;
}
Inv(a,b,(dep+1)>>1,midlen);
static Poly tmp;
while((dep<<1)>midlen)
midlen<<=1;
for(int i=0;i<dep;i++)
tmp.data[i]=a.data[i];
for(int i=dep;i<midlen;i++)
tmp.data[i]=0;
NTT(tmp,1,midlen);
NTT(b,1,midlen);
for(int i=0;i<midlen;i++)
b.data[i]=1LL*b.data[i]*((2-1LL*tmp.data[i]*b.data[i])%MOD+MOD)%MOD;
NTT(b,0,midlen);
for(int i=dep;i<midlen;i++)
b.data[i]=0;
b.t=dep-1;
}
void sqrt(Poly a,Poly &b,int &midlen,int dep){
if(dep==1){
b.data[0]=1;
b.t=dep-1;
return;
}
sqrt(a,b,midlen,(dep+1)>>1);
while((dep<<1)>(midlen))
midlen<<=1;
static Poly tmp1,tmp2,tmp3;
tmp1=b;tmp3=b;
save(tmp1,dep-1);
save(tmp2,-1);
save(tmp3,dep-1);
int midlent=1;
for(int i=0;i<dep;i++)
tmp1.data[i]=(tmp1.data[i]*2)%MOD;
Inv(tmp1,tmp2,dep,midlent);
mul(b,tmp3);
for(int i=0;i<dep;i++)
b.data[i]=(b.data[i]+a.data[i])%MOD;
mul(b,tmp2);
for(int i=dep;i<midlen;i++)
b.data[i]=0;
b.t=dep-1;
}
Poly c,C;
int n,m;
signed main(){
scanf("%lld %lld",&n,&m);
c.t=100000;
for(int i=1;i<=n;i++){
int x;
scanf("%lld",&x);
c.data[x]=1;
}
for(int i=0;i<=c.t;i++)
c.data[i]=((-4LL*c.data[i])%MOD+MOD)%MOD;
c.data[0]=(1+c.data[0])%MOD;
int midlen=1;
sqrt(c,C,midlen,c.t+1);
C.data[0]=(1+C.data[0])%MOD;
midlen=1;
save(c,-1);
Inv(C,c,C.t+1,midlen);
for(int i=1;i<=m;i++)
printf("%lld\n",(c.data[i]*2)%MOD);
return 0;
}
CF438E The Child and Binary Tree的更多相关文章
- [题解] CF438E The Child and Binary Tree
CF438E The Child and Binary Tree Description 给一个大小为\(n\)的序列\(C\),保证\(C\)中每个元素各不相同,现在你要统计点权全在\(C\)中,且 ...
- 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( ...
- cf438E. The Child and Binary Tree(生成函数 多项式开根 多项式求逆)
题意 链接 Sol 生成函数博大精深Orz 我们设\(f(i)\)表示权值为\(i\)的二叉树数量,转移的时候可以枚举一下根节点 \(f(n) = \sum_{w \in C_1 \dots C_n} ...
- CF438E The Child and Binary Tree(生成函数,NTT)
题目链接:洛谷 CF原网 题目大意:有 $n$ 个互不相同的正整数 $c_i$.问对于每一个 $1\le i\le m$,有多少个不同形态(考虑结构和点权)的二叉树满足每个点权都在 $c$ 中出现过, ...
- CF438E The Child and Binary Tree(生成函数+多项式开根+多项式求逆)
传送门 可以……这很多项式开根模板……而且也完全不知道大佬们怎么把这题的式子推出来的…… 首先,这题需要多项式开根和多项式求逆.多项式求逆看这里->这里,这里讲一讲多项式开根 多项式开方:已知多 ...
- 【CF438E】The Child and Binary Tree(多项式运算,生成函数)
[CF438E]The Child and Binary Tree(多项式运算,生成函数) 题面 有一个大小为\(n\)的集合\(S\) 问所有点权都在集合中,并且点权之和分别为\([0,m]\)的二 ...
- Codeforces 250 E. The Child and Binary Tree [多项式开根 生成函数]
CF Round250 E. The Child and Binary Tree 题意:n种权值集合C, 求点权值和为1...m的二叉树的个数, 形态不同的二叉树不同. 也就是说:不带标号,孩子有序 ...
- [codeforces438E]The Child and Binary Tree
[codeforces438E]The Child and Binary Tree 试题描述 Our child likes computer science very much, especiall ...
- Codeforces 438E. The Child and Binary Tree 多项式,FFT
原文链接www.cnblogs.com/zhouzhendong/p/CF438E.html 前言 没做过多项式题,来一道入门题试试刀. 题解 设 $a_i$ 表示节点权值和为 $i$ 的二叉树个数, ...
随机推荐
- ubuntu 忽略文件的50unattended升级问题
ubuntu出现这样问题 既然说那个文件扩展名无效,那干脆直接把那个文件删掉 sudo rm /etc/apt/apt.conf.d/20auto-upgrades.ucf-old 删掉之后应该就不会 ...
- 关于 systemctl --user status 报错的问题
关于 systemctl --user enable mpd 报错: Failed to connect to bus: No such file or directory 因为arch脚本中,sys ...
- dedecms (织梦)漏洞&exp整理
[通杀]dedecms plussearch.php 注入漏洞利用方式看结果如果提示Safe Alert: Request Error step 2 !那么直接用下面的exp查看源代码打印帮助1 /p ...
- js的简单介绍
1.js的介绍 js全称叫javascript,但不是java,他是一门前台语言,而java是后台语言. js的作者是布兰登艾奇. 前台语言:运行在客户端的 后台语言:跟数据库有关的. 2.能干什么? ...
- 使用强类型DataSet增加数据并获取自动增长的ID
使用强类型的DataSet可以方便的操作数据库:有时候我们会对表的ID设置为自动增长,并且需要在插入数据后获取新插入数据的ID,按以下方法即可达到目的: 一. 首先建立一个表,id为自动增加, ...
- python全栈开发 * 36知识点汇总 * 180721
36 操作系统的发展史 进程一.手工操作--穿孔卡片 1.内容: 程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把程序和数据输入计算机内存,接着通过控制 台开关启动程序针对 ...
- 如何将AAC音频转换成MP3格式
我们应该怎样将AAC音频转换成MP3格式呢?AAC是一种专为声音数据设计的文件压缩格式,相对于MP3音频来说更加高效,性价比跟高.但是因为MP3音频格式的通用性,我们还是时常需要将AAC音频转换成MP ...
- 【立体几何】分类讨论很细节 Gym - 101967I Путешествие по тору
http://codeforces.com/gym/101967/attachments 题意:定义了一个甜甜圈.(torus) 不是让你二重积分啦233 现在有一个星球是甜甜圈形状的,它有四条很关键 ...
- javascript call apply
call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向.因为 JavaScript 的函数存在「定义时上下文」和「 ...
- spark-sql集合的“条件过滤”,“合并”,“动态类型映射DataFrame”,“存储”
List<String> basicList = new ArrayList<String>(); basicList.add("{\"name\" ...