[题解] CF438E The Child and Binary Tree
CF438E The Child and Binary Tree
Description
给一个大小为\(n\)的序列\(C\),保证\(C\)中每个元素各不相同,现在你要统计点权全在\(C\)中,且点权和为\(m\)的二叉树个数,并对\(998244353\)取模。
\(n,m \le 10^5\)
Solution
\(998244353\)?这很多项式......
总之先颓柿子好了。
令\(f_n\)表示权值和为\(n\)的二叉树个数,\(g_n\)表示权值\(n\)是否出现在\(C\)中。
那么枚举根节点的权值,然后在枚举左右儿子的权值和,即\((n>0)\)
\]
特别的\(f_0=1\)。
上面的柿子非常卷积吧!
令\(F(x) = \sum\limits_{n=0}^{\infty} f_nx^n,G(x) = \sum\limits_{n=0}^{\infty}g_nx^n\),那么
\]
加一是因为\(f_0=1\)。
我们的目标就是把\(F(x)\)搞出来,先移项
\]
然后解方程得到
\]
有两个解,咋办? 对着样例各跑一遍
不慌,我们知道当\(x=0\)时,\(F(x)=1\)。
所以分类讨论一下
取加号时,当\(x \to 0\),楼上分子会趋于\(1+1 = 2\),楼下分母会趋于\(0\),炸了......
如果取减号,楼上楼下都会趋于\(0\),这是我们想要的。
所以
\]
没了?
并没有......我们发现这个柿子还没有办法算出\(F\),因为\(2G\)可能是\(0\)。
我们取倒数再给他变一变,得到
\]
这样就非常\(nice\)。
因为我们只关心\(f_1...f_m\),所以在\(mod \ x^{m+1}\)的意义下开根求逆就好了。
#include <bits/stdc++.h>
using namespace std;
const int N=3e5+10,P=998244353,gen=3,igen=(P+1)/gen;
inline int add(int x,int y){
return x+y>=P?x+y-P:x+y;
}
inline int sub(int x,int y){
return x-y<0?x-y+P:x-y;
}
inline int fpow(int x,int y){
int ret=1; for (x%=P;y;y>>=1,x=1ll*x*x%P)
if (y&1) ret=1ll*ret*x%P;
return ret;
}
inline int sqr(int x){
return 1ll*x*x%P;
}
namespace Poly{
int rev[N];
void init(int n){
for (int i=0;i<n;i++)
rev[i]=rev[i>>1]>>1|((i&1)?n>>1:0);
}
void ntt(int *f,int n,int flg){
for (int i=0;i<n;i++) if (rev[i]<i) swap(f[i],f[rev[i]]);
for (int k=1,len=2;len<=n;len<<=1,k<<=1){
int wn=fpow(flg==1?gen:igen,(P-1)/len);
for (int i=0;i<n;i+=len){
for (int w=1,j=i;j<i+k;j++,w=1ll*w*wn%P){
int tmp=1ll*w*f[j+k]%P;
f[j+k]=sub(f[j],tmp),f[j]=add(f[j],tmp);
}
}
}
if (flg==-1){
int inv=fpow(n,P-2);
for (int i=0;i<n;i++) f[i]=1ll*f[i]*inv%P;
}
}
void getinv(int *f,int n,int *G){
if (n==1){G[0]=fpow(f[0],P-2);return;}
getinv(f,(n+1)>>1,G); static int F[N];
int limit=1; while(limit<=2*n)limit<<=1; init(limit);
for (int i=0;i<limit;i++) F[i]=i>=n?0:f[i],G[i]=i>=n?0:G[i];
ntt(F,limit,1),ntt(G,limit,1);
for (int i=0;i<limit;i++) G[i]=1ll*G[i]*sub(2,1ll*F[i]*G[i]%P)%P;
ntt(G,limit,-1);
for (int i=n;i<limit;i++) G[i]=0;
}
void getsqrt(int *f,int n,int *G){
if (n==1){G[0]=1;return;}
getsqrt(f,(n+1)>>1,G);
int limit=1; while(limit<=n*2)limit<<=1; init(limit);
static int F[N],H[N],iH[N];
for (int i=0;i<limit;i++)
G[i]=i>=n?0:G[i],F[i]=i>=n?0:f[i],H[i]=i>=n?0:2ll*G[i]%P;
getinv(H,n,iH);
ntt(F,limit,1),ntt(iH,limit,1),ntt(G,limit,1);
for (int i=0;i<limit;i++) G[i]=1ll*add(F[i],sqr(G[i]))*iH[i]%P;
ntt(G,limit,-1);
for (int i=n;i<limit;i++) G[i]=0;
}
}
int n,m,g[N],f[N],sqg[N];
int main(){
scanf("%d%d",&n,&m);
for (int i=0,c;i<n;i++) scanf("%d",&c),g[c]=1;
for (int i=1;i<=m;i++) g[i]=sub(P,4ll*g[i]%P);
g[0]=1;
Poly::getsqrt(g,m+1,sqg);
sqg[0]++;
Poly::getinv(sqg,m+1,f);
for (int i=1;i<=m;i++) printf("%d\n",2ll*f[i]%P);
return 0;
}
[题解] CF438E The Child and Binary Tree的更多相关文章
- 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
思路 设F(x)的第x项系数为权值和为x的答案 题目中要求权值必须在集合中出现,这个不好处理,考虑再设一个C,C的第x项如果是1代表x出现在值域里,如果是0,代表x没有出现在值域里,然后由于二叉树可以 ...
- 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]\)的二 ...
- [codeforces438E]The Child and Binary Tree
[codeforces438E]The Child and Binary Tree 试题描述 Our child likes computer science very much, especiall ...
- Codeforces 250 E. The Child and Binary Tree [多项式开根 生成函数]
CF Round250 E. The Child and Binary Tree 题意:n种权值集合C, 求点权值和为1...m的二叉树的个数, 形态不同的二叉树不同. 也就是说:不带标号,孩子有序 ...
- 【题解二连发】Construct Binary Tree from Inorder and Postorder Traversal & Construct Binary Tree from Preorder and Inorder Traversal
LeetCode 原题链接 Construct Binary Tree from Inorder and Postorder Traversal - LeetCode Construct Binary ...
随机推荐
- [LeetCode] 326. Power of Three + 342. Power of Four
这两题我放在一起说是因为思路一模一样,没什么值得研究的.思路都是用对数去判断. /** * @param {number} n * @return {boolean} */ var isPowerOf ...
- 对象内置的方法/内置的 Symbol 值
内置的 Symbol 值 除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法. Symbol.hasInstance 对象的Symbo ...
- Python测试进阶——(1)安装Python测试相关模块
安装python 安装pip yum -y install epel-release yum -y install python-pip 安装psutil 参考:https://www.cnblogs ...
- springMVC,spring和Hibernate整合(重要)
springMVC,spring和Hibernate整合 https://my.oschina.net/hugohxb/blog/184715 第一步:搭建一个springmvc工程,需要的jar有: ...
- css - flex 定义排列方向
flex-direction定义伸缩项目放置在伸缩容器的排列方向,对应有四个值: (1)row:从左到右或从右到左 (2)row-reverse:与row属性相反 (3)column:从上到下排列 ( ...
- Day5-T3
原题目 要开运动会了,神犇学校的n个班级要选班服,班服共有100种样式,编号1~100.现在每个班都挑出了一些样式待选,每个班最多有100个待选的样式.要求每个班最终选定一种样式作为班服,且该班的样式 ...
- 六、Vue-Router:基础路由处理、路由提取成单独文件、路由嵌套、路由传参数、路由高亮、html5的history使用
一.vue-router的安装 官网文档 [官网]:https://cn.vuejs.org/v2/guide/routing.html [router文档]:https://router.vuejs ...
- L2d插件
<script src="https://blog-static.cnblogs.com/files/yyhh/L2Dwidget.min.js"></scrip ...
- wireshark混杂模式
来自:https://blog.csdn.net/mukami0621/article/details/78645825 通过设置网卡为混杂模式就能捕获局域网内所有发包内容,包括非广播包和非发给自己主 ...
- mysql基本知识的总结
Mysql基本sql知识 Navicat快捷方式: 选中当前行 在行尾:shift+home 在行首:shift+end 执行当前行:ctrl+shift+R 复制当前行:ctrl+D 显示所有数据库 ...