传送门

Sol

设 \(f_x\) 表示权值为 \(x\) 的二叉树的个数

设 \(s_x\) 表示是否有 \(x\) 这种权值可以选择

那么

\[f_n=\sum_{i=0}^{n}\sum_{j=0}^{n-i}f_jf_{n-i-j}s_i
\]

构造

\[F(x)=\sum_{i=0}f_ix^i
\]

\[S(x)=\sum_{i=0}s_ix^i
\]

由于 \(s_0=0,f_0=1\)

那么

\(F^2(x)S(x)=F(x)-1\)

所以可以求得

\[F(x)=\frac{1\pm \sqrt{1-4S(x)}}{2S(x)}
\]

由于 \(F(0)=1,S(0)=0\) 所以

\[F(x)=\frac{1- \sqrt{1-4S(x)}}{2S(x)}
\]

正是因为 \(S(0)=0\) 没有办法求逆

所以化简得到

\[F(x)=\frac{2}{1+ \sqrt{1-4S(x)}}
\]

开根(常数项是 \(1\) 所以不用二次剩余)+求逆即可

# include <bits/stdc++.h>
using namespace std;
typedef long long ll; const int maxn(4e5 + 5);
const int mod(998244353);
const int inv2(499122177); inline int Pow(ll x, int y) {
register ll ret = 1;
for (; y; y >>= 1, x = x * x % mod)
if (y & 1) ret = ret * x % mod;
return ret;
} inline void Inc(int &x, int y) {
if ((x += y) >= mod) x -= mod;
} int a[maxn], b[maxn], c[maxn], w[2][maxn], deg, r[maxn], l; inline void Init(int n) {
register int i, k, wn, iwn;
for (deg = 1, l = 0; deg < n; deg <<= 1) ++l;
for (i = 0; i < deg; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
for (i = 1; i < deg; i <<= 1) {
w[0][0] = w[1][0] = 1;
wn = Pow(3, (mod - 1) / (i << 1)), iwn = Pow(wn, mod - 2);
for (k = 1; k < i; ++k) {
w[0][deg / i * k] = 1LL * w[0][deg / i * (k - 1)] * wn % mod;
w[1][deg / i * k] = 1LL * w[1][deg / i * (k - 1)] * iwn % mod;
}
}
} inline void NTT(int *p, int opt) {
register int i, j, k, t, wn, x, y;
for (i = 0; i < deg; ++i) if (r[i] < i) swap(p[r[i]], p[i]);
for (i = 1; i < deg; i <<= 1)
for(t = i << 1, j = 0; j < deg; j += t)
for (k = 0; k < i; ++k) {
wn = w[opt == -1][deg / i * k];
x = p[j + k], y = 1LL * wn * p[i + j + k] % mod;
p[j + k] = x + y, p[i + j + k] = x - y;
if (p[j + k] >= mod) p[j + k] -= mod;
if (p[i + j + k] < 0) p[i + j + k] += mod;
}
if (opt == -1) {
wn = Pow(deg, mod - 2);
for (i = 0; i < deg; ++i) p[i] = 1LL * p[i] * wn % mod;
}
} int n, m, f[maxn], g[maxn], s[maxn]; void Inv(int *p, int *q, int len) {
if (len == 1) {
q[0] = Pow(p[0], mod - 2);
return;
}
Inv(p, q, len >> 1);
register int i, tmp = len << 1;
for (i = 0; i < len; ++i) a[i] = p[i], b[i] = q[i];
Init(tmp), NTT(a, 1), NTT(b, 1);
for (i = 0; i < tmp; ++i) a[i] = 1LL * a[i] * b[i] % mod * b[i] % mod;
NTT(a, -1);
for (i = 0; i < len; ++i) q[i] = (2LL * q[i] + mod - a[i]) % mod;
for (i = 0; i < tmp; ++i) a[i] = b[i] = 0;
} void Sqrt(int *p, int *q, int len) {
if (len == 1) {
q[0] = sqrt(p[0]);
return;
}
Sqrt(p, q, len >> 1), Inv(q, c, len);
register int i, tmp = len << 1;
for (i = 0; i < len; ++i) a[i] = p[i];
Init(tmp), NTT(a, 1), NTT(c, 1);
for (i = 0; i < tmp; ++i) a[i] = 1LL * a[i] * c[i] % mod;
NTT(a, -1);
for (i = 0; i < len; ++i) q[i] = 1LL * (q[i] + a[i]) % mod * inv2 % mod;
for (i = 0; i < tmp; ++i) a[i] = c[i] = 0;
} int main() {
register int i, len, v;
scanf("%d%d", &n, &m);
for (i = 1; i <= n; ++i) scanf("%d", &v), ++s[v];
for (len = 1; len <= m; len <<= 1);
for (i = 1; i <= m; ++i) s[i] = 1LL * s[i] * 4 % mod, s[i] = mod - s[i];
s[0] = 1, Sqrt(s, f, len), Inc(f[0], 1), Inv(f, g, len);
for (i = 0; i < len; ++i) g[i] = 2LL * g[i] % mod;
for (i = 1; i <= m; ++i) printf("%d\n", g[i]);
return 0;
}

BZOJ3625: 小朋友和二叉树的更多相关文章

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

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

  2. [Codeforces438E][bzoj3625] 小朋友和二叉树 [多项式求逆+多项式开根]

    题面 传送门 思路 首先,我们把这个输入的点的生成函数搞出来: $C=\sum_{i=0}^{lim}s_ix^i$ 其中$lim$为集合里面出现过的最大的数,$s_i$表示大小为$i$的数是否出现过 ...

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

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

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

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

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

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

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

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

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

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

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

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

  9. 【BZOJ3625】【CF438E】小朋友和二叉树 NTT 生成函数 多项式开根 多项式求逆

    题目大意 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\ldots ,c_n\).如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合\(\{c_1,c_2,\ldots ,c_n\ ...

随机推荐

  1. K:java中的安全模型(沙箱机制)

    本博文整合自:Java安全--理解Java沙箱.Java 安全模型介绍.Java的沙箱机制原理入门 相关介绍:  我们都知道,程序员编写一个Java程序,默认的情况下可以访问该机器的任意资源,比如读取 ...

  2. Java中关键字final用法

    ///首先声明,本文转载自博客园的海子,链接:http://www.cnblogs.com/dolphin0520/p/3736238.html 浅析Java中的final关键字 谈到final关键字 ...

  3. php 逐行读取文本文件

    在读取文本时,我们要注意一个事情,那就是换行符,应为我们在写文档时会手动换行,这个换行符需不需要保存就要看自己的需求了. 这里封装了两个方法,一个保留换行,一个不保留.$path为文件路径+文件名 1 ...

  4. JavaIO系统

    为了方便记忆,特将IO中涉及的类进行整理如下: 1.File类 提供了目录操作,查看文件属性等. 2.java IO类层次 面向字节流的类为InputStream.OutputStream:面向字符流 ...

  5. VUE源代码调试方法

    前两条出自: https://link.zhihu.com/?target=http%3A//www.orzzone.com/vuejs-project-debug.html https://www. ...

  6. 20190416 OSX系统使用VMware Fusion安装CentOS7踩的那些坑

    一.创建虚拟机 (1)在虚拟机资源库中点击[+添加]按钮,选择“新建...”选项 (2)选择创建自定义虚拟机 (3)选择系统类型为CentOS (4)选择虚拟磁盘类型 (5)选择虚拟机存储位置:点击[ ...

  7. Altium Designer安装孔周围放置圆形Polygon Pour Cutout

    1.  在Keep-Out层画2个圆, 中间的圆用作安装孔, 外圆做为禁止覆铜层. 这样做的好处是,放好安装孔后, 外面禁止覆铜层也覆不上铜, 防止螺钉与覆铜接触. 2. 选中外圆, Tools -& ...

  8. ASP.NET MVC利用ActionLink实现动态组合查询

    一个文件传输数据表,内有日期.传输协议.传输方向(上传或下载).文件名等信息,完整的表内容显示如下: 现在需要分类查询,即按照协议和传输方向查询.单独的分类查询问题并不大,比如,按协议查询,在View ...

  9. vSphere通过Client创建Centos7主机

    准备: vSphere Client 客户端 Centos7官方镜像,本次采用的是CentOS-7-x86_64-Minimal-1511.iso 创建过程: 1.登录vSphere虚拟主机,输入账户 ...

  10. 【gcc】命令记录

    编译程序gcc -o <eecutable> <soure_code.c>