传送门

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. 39.oracle高级篇

    标题说是高级篇,其实也就是相对于基础篇来说的,也不是很深奥,自己平时工作中也都会用到,这里回忆的并不是特别冷门的知识,不要掉以轻心,以为“高级”就觉得工作中不会用到了. 一.select into 和 ...

  2. python学习,day4:装饰器的使用示例2

    这个例子比较复杂 # coding=utf-8 # Author: RyAn Bi user,passwd = ' #输入用户名密码 def auth(auth_type): #装饰器第一层,确定鉴权 ...

  3. [DPF] DPF 常见的问题

    问题一: SQL6031N  Error in the db2nodes.cfg file at line number "5".  Reason code "12&qu ...

  4. Android多媒体之照相机

    1.调用系统的照相机 public void click(View view) { // 激活系统的照相机拍照 Intent intent = new Intent("android.med ...

  5. SpringBoot 整合 Logback

    Logback is intended as a successor to the popular log4j project, picking up where log4j leaves off.L ...

  6. ListenableFuture in Guava

    ListenableFuture的说明 并发编程是一个难题,但是一个强大而简单的抽象可以显著的简化并发的编写.出于这样的考虑,Guava 定义了 ListenableFuture接口并继承了JDK c ...

  7. C#(winform)的label自动换行

    Label 是没有自动换行属性的,不像Textbox有WordWrap属性 尽管没有自动换行的属性,但也能够自动换行, 首先 AutoSize改成false; 然后调整 Label的大小,长和宽 (也 ...

  8. typeof, offsetof 和container_of

    要理解Linux中实现的双向循环链表("侵入式"链表),首先得弄明白宏container_of. 本文尝试从gcc的关键字typeof和宏offsetof入手,循序渐进地剖析宏co ...

  9. mvn pom

    使用本地指定目录下jar包 <dependency> <groupId>com.myself.abc</groupId> <artifactId>sam ...

  10. Comet:基于 HTTP 长连接的“服务器推”技术(转载)

    “服务器推”技术的应用 传统模式的 Web 系统以客户端发出请求.服务器端响应的方式工作.这种方式并不能满足很多现实应用的需求,譬如: 监控系统:后台硬件热插拔.LED.温度.电压发生变化: 即时通信 ...