[题解] 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 ...
随机推荐
- 17 MySQL的小技巧
1.正则表达式的使用 ^ 在字符串开始处进行匹配 $ 在字符串末尾处进行匹配 . 匹配任意单个字符,包括换行符 [...] 匹配出括号内的任意字符 [^...] 匹配不出括号内的任意字符 a* ...
- D - Recommendations
就是有n组,每组的数量是num,只能增加数字,增加的代价为t,求能使所有组的数量都不同的最小代价. #include<bits/stdc++.h> #define N 200005 #de ...
- 解决win10创建Django工程,运行django-admin.py startproject 工程名,失败的问题
在看我这篇教程的前提是你应该已经正确装好python和Django了,好了,废话不说了,正题走你!你现在是不是很纠结自己运行django-admin.py startproject 工程名 ...
- idea2018破解到2099年
破解的详细过程: 1.从下面地址下载一个jar包,名称是 JetbrainsCrack-3.1-release-enc.jar 下载地址链接: https://pan.baidu.com/s/1WU5 ...
- 洛谷 P3801 红色的幻想乡
题目背景 蕾米莉亚的红雾异变失败后,很不甘心. 题目描述 经过上次失败后,蕾米莉亚决定再次发动红雾异变,但为了防止被灵梦退治,她决定将红雾以奇怪的阵势释放. 我们将幻想乡看做是一个n*m的方格地区,一 ...
- IDEA开发spring boot应用时 application.yml 或 application.properties 自定义属性提示
在使用spring boot开发过程中,经常会定义一些应用自己的属性,直接写到application配置文件中使用@Value注解进行使用,这样使用也没有什么问题.不过我认为更优雅的方式是定义自己的属 ...
- 033、Java中使用简化运算符
01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...
- spark aggregate算子
spark aggregate源代码 /** * Aggregate the elements of each partition, and then the results for all the ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-minus
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- 一个有意思的html验证码: namesilo验证码
买域名的时候看到的一个验证码,感觉蛮有意思的(https://www.namesilo.com/create_account.php),这个质感看上去就不一样: 查看页面源码,果然这个验证码是用htm ...