Codeforces 438E The Child and Binary Tree - 生成函数 - 多项式
题目传送门
题目大意
每个点的权值$c\in {c_{1}, c_{2}, \cdots, c_{n}}$,问对于每个$1\leqslant s\leqslant m$有多少种不同的这样的有根二叉树满足所有点的点权和等于$s$。
先考虑一下怎么用dp来做。
设$f_{n}$表示点权和为$n$的满足条件的二叉树的个数,那么有:
$f_{n} = \sum_{c \in C}\sum_{i = 0}^{n - c}f_{i}f_{n - c - i}$
初值满足$f_{0} = 1$。
注意到右边的式子有点像卷积,考虑$f_{n}$的普通生成函数$F(x) = \sum_{n = 0}f_{n}x^{n}$。
将$F(x)$平方就能得到$f\otimes f$的生成函数。我们用它替换右半边,得到了:
$F(x) = \sum_{c \in C}x^{c}F^2(x) + 1$
设某个常数$A = \sum_{c \in C}x^{c}$,则有$A\cdot F^2(x) - F(x) + 1$。
解得$F_{1}(x) = \frac{1 + \sqrt{1 - 4A}}{2A}, F_{2}(x) = \frac{1 - \sqrt{1 - 4A}}{2A} = \frac{1 - (1 - 4A)}{2A\sqrt{1 + 4A}} = \frac{2}{\sqrt{1 + 4A}}$。
我们考虑$F_{1}(x)$的分母的常数项,它是2,分子的常数项为0,然后求逆的时候就会出事情。
但是$F_{2}(x)$可以通过恒等变换使得分母的常数项为非0。
然后做一次多项式开根,一次多项式求逆就做完了。
Code
/**
* Codeforces
* Problem#438E
* Accepted
* Time: 1091ms
* Memory: 5100k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; const int N = ;
const int bzmax = ;
const int M = ;
const int g = ;
const int inv2 = (M + ) >> ; int qpow(int a, int p) {
if (p < )
p += M - ;
int rt = , pa = a;
for ( ; p; p >>= , pa = pa * 1ll * pa % M)
if (p & )
rt = rt * 1ll * pa % M;
return rt;
} int add(int a, int b) {
return ((a += b) >= M) ? (a - M) : (a);
} int sub(int a, int b) {
return ((a -= b) < ) ? (a + M) : (a);
} class NTT {
public:
int gn[bzmax], _gn[bzmax]; NTT() {
for (int i = , L = ; i < bzmax; i++, L <<= ) {
gn[i] = qpow(g, (M - ) / L);
_gn[i] = qpow(g, -(M - ) / L);
}
} void operator () (int* f, int len, int sgn) {
for (int i = , j = len >> , k; i < len - ; i++, j += k) {
if (i < j)
swap(f[i], f[j]);
for (k = len >> ; j >= k; j -= k, k >>= );
} for (int b = , t = ; b <= len; b <<= , t++) {
int wn = ((sgn > ) ? (gn[t]) : (_gn[t])), w = , hb = b >> ;
for (int i = ; i < len; i += b, w = )
for (int j = i; j < i + hb; j++, w = w * 1ll * wn % M) {
int a = f[j], b = f[j + hb] * 1ll * w % M;
f[j] = add(a, b);
f[j + hb] = sub(a, b);
}
} if (sgn < ) {
int invlen = qpow(len, -);
for (int i = ; i < len; i++)
f[i] = f[i] * 1ll * invlen % M;
}
} int correctLen(int n) {
int m = ;
while (m < n) m <<= ;
return m;
}
}NTT; template<typename T>
void pcopy(T* ns, T* ne, const T* os) {
for ( ; ns != ne; *ns = *os, ns++, os++);
} template<typename T>
void pfill(T* ps, T* pt, T val) {
for ( ; ps != pt; *ps = val, ps++);
} void debug(const int* f, int n) {
for (int i = ; i < n; i++)
cerr << f[i] << " ";
cerr << endl;
} void pol_inverse(int *f, int *g, int n) {
static int h[N];
if (n == )
g[] = qpow(f[], -);
else {
pol_inverse(f, g, (n + ) >> ); int t = NTT.correctLen(n << | );
pcopy(h, h + n, f);
pfill(h + n, h + t, );
NTT(h, t, );
NTT(g, t, );
for (int i = ; i < t; i++)
g[i] = g[i] * 1ll * sub(, g[i] * 1ll * h[i] % M) % M;
NTT(g, t, -);
pfill(g + n, g + t, );
}
} void pol_sqrt(int *f, int *g, int n) {
static int C[N], D[N];
if (n == )
g[] = ;
else {
pol_sqrt(f, g, (n + ) >> ); int t = NTT.correctLen(n << );
pcopy(C, C + n, f);
pfill(C + n, C + t, );
pfill(D, D + t, );
pol_inverse(g, D, n);
NTT(C, t, );
NTT(D, t, );
NTT(g, t, );
for (int i = ; i < t; i++)
g[i] = add(C[i] * 1ll * D[i] % M, g[i]) * 1ll * inv2 % M;
NTT(g, t, -);
pfill(g + n, g + t, );
}
} int n, m;
int C[N], qC[N]; inline void init() {
scanf("%d%d", &n, &m);
for (int i = , x; i <= n; i++) {
scanf("%d", &x);
if (x <= m)
C[x] = -;
}
} inline void solve() {
C[]++, m++;
pol_sqrt(C, qC, m);
qC[]++;
pfill(C, C + m, );
pol_inverse(qC, C, m);
for (int i = ; i < m; i++)
printf("%d\n", add(C[i], C[i]));
} int main() {
init();
solve();
return ;
}
Codeforces 438E The Child and Binary Tree - 生成函数 - 多项式的更多相关文章
- Codeforces 438E The Child and Binary Tree [DP,生成函数,NTT]
洛谷 Codeforces 思路 看到计数和\(998244353\),可以感觉到这是一个DP+生成函数+NTT的题. 设\(s_i\)表示\(i\)是否在集合中,\(A\)为\(s\)的生成函数,即 ...
- Codeforces 438E. The Child and Binary Tree 多项式,FFT
原文链接www.cnblogs.com/zhouzhendong/p/CF438E.html 前言 没做过多项式题,来一道入门题试试刀. 题解 设 $a_i$ 表示节点权值和为 $i$ 的二叉树个数, ...
- 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(多项式运算,生成函数)
[CF438E]The Child and Binary Tree(多项式运算,生成函数) 题面 有一个大小为\(n\)的集合\(S\) 问所有点权都在集合中,并且点权之和分别为\([0,m]\)的二 ...
- 【CF】438E. The Child and Binary Tree
http://codeforces.com/contest/438/problem/E 题意:询问每个点权值在 $c_1, c_2, ..., c_m$ 中,总权值和为 $s$ 的二叉树个数.请给出每 ...
- 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( ...
- CF 438E The Child and Binary Tree
BZOJ 3625 吐槽 BZOJ上至今没有卡过去,太慢了卡得我不敢交了…… 一件很奇怪的事情就是不管是本地还是自己上传数据到OJ测试都远远没有到达时限. 本题做法 设$f_i$表示权值为$i$的二叉 ...
- bzoj 3625(CF 438E)The Child and Binary Tree——多项式开方
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3625 http://codeforces.com/contest/438/problem/E ...
- Codeforces 250 E. The Child and Binary Tree [多项式开根 生成函数]
CF Round250 E. The Child and Binary Tree 题意:n种权值集合C, 求点权值和为1...m的二叉树的个数, 形态不同的二叉树不同. 也就是说:不带标号,孩子有序 ...
随机推荐
- python基础类型—元祖
元组 被称为只读列表,即数据可以被查询,但不能被修改,所以,字符串的切片操作同样适用于元组. 例:(1,2,3)("a","b","c") ...
- 添加ll命令
$ vim ~/.bashrcalias ll='ls -l' #加入此行 ps:加入后肯能无法当场起作用,执行该句: source ~/.bashrc
- java基础---->Java的格式化输出
在JavaSe5中,推出了C语言中printf()风格的格式化输出.这不仅使得控制输出的代码更加简单,同时也给与Java开发者对于输出格式与排列更大的控制能力.今天,我们开始学习Java中的格式化输出 ...
- Jquery 获取 radio选中值,select选中值
随着Jquery的作用越来越大,使用的朋友也越来越多.在Web中,由于CheckBox.Radiobutton .DropDownList等控件使用的频率比较高,就关系到这些控件在Jquery中的操作 ...
- 五子棋棋盘布局 table和ul哪个好
想要在页面布局以上棋盘,可以用ul li 布局,但却有明显的缺点: 1.两行两列:ul li 下面如果再放li 会出错,只能是放其他的,比如div. 或者放li *行*列: 但是这样有两个明显缺陷: ...
- 用VsCode写Markdown
Markdown 基本语法 段落 非常自然,一行文字就是一个段落. 比如: 这是一个段落 会被解释成: <p>这是一个段落.</p> 如果你需要另起一段,请在两个段落之间隔一个 ...
- Spark Streaming实战演练
一.spark streaming简介 Streaming是一种数据传输技术,它把客户机收到的数据变成一个稳定连续的流,源源不断的输出,使用户听到的声音和图像十分稳定,而用户在整个文件传输完成开始前就 ...
- C++11 std::call_once:保证函数在任何情况下只调用一次
std::call_once的作用是很简单的, 就是保证函数或者一些代码段在并发或者多线程的情况下,始终只会被执行一次.比如一些init函数,多次调用可能导致各种奇怪问题. 给个例子: #includ ...
- HDFS,MapReduce,Hive,Hbase 等之间的关系
HDFS: HDFS是GFS的一种实现,他的完整名字是分布式文件系统,类似于FAT32,NTFS,是一种文件格式,是底层的. Hive与Hbase的数据一般都存储在HDFS上.Hadoop HDFS为 ...
- 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业
2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...