传送门

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. package.json和bower的参数解释

    package.json和bower的参数解释   一.package.json解释: package.json是用来声明项目中使用的模块,这样新的环境部署时,只要在package.json文件所在的 ...

  2. python3.6使用scrapy报错

    用python做爬虫的,肯定熟悉scrapy,不过新手安装总是会遇到各种奇葩错误. 错误一:building 'twisted.test.raiser' extensionerror: Microso ...

  3. P4542 [ZJOI2011]营救皮卡丘

    题目链接 题意分析 我们仔细分析一下 发现题目要求用最多\(k\)条路径实现最小权覆盖 首先由于最小路径覆盖针对的是有向图 但是这是一个无向图 所以我们面向对象编程 我们维护一个数组\(d[i][j] ...

  4. localstrage、cookie、session等跨域和跨页面监听更新问题

    localstrage.cookie.session等跨域和跨页面监听更新问题

  5. 2018青岛网络赛G - Couleur 区间上的启发式合并

    题意:给出\(a[1...n]\),共\(n\)次操作,每次删除一个位置\(p_i\)(强制在线),此时区间会变为两个分离的区间,求每次操作的最大区间逆序对 首先要知道必要的工具,按权值建立的主席树可 ...

  6. 成倍提高服务器的负载能力:浅谈Jexus的ASP.NET前置缓存技术

    一.什么是“ASP.NET前置缓存”     ASP.NET前置缓存,是Jexus特色功能之一,是指Jexus把开发者指定的ASP.NET网页某一时刻的内容,缓存到专用的高速缓冲区中,在指定的时间内, ...

  7. Highcharts图表.net版开源,支持webform 和 mvc3,完全开源

    Highcharts是一个制作图表的纯Javascript类库,主要特性如下: 兼容性:兼容当今所有的浏览器,包括iPhone.IE和火狐等等: 对个人用户完全免费: 纯JS,无BS: 支持大部分的图 ...

  8. HTML 权重标签的使用

    <H>标签通常使用<H1><H2><H3>这3个标签是有权重加分的,<H4>用于无用途的文字标记等 非重要相关字. <H1>有别 ...

  9. Javac的命令

    关于命令,还可以查看<Java 7程序设计>一书后面的附录A As per javac source docs, there are 4 kinds of options: standar ...

  10. C#的托管和非托管的简单理解

    应该说“托管”一词是和.net概念一起出生的, 我们都知道以前的开发工具无论是Delphi.VB编译出的dll或exe文件都是二进制文件, 可以被操作系统直接识别.而微软为了和JAVA火拼,实现跨平台 ...