BZOJ 3625

吐槽

BZOJ上至今没有卡过去,太慢了卡得我不敢交了……

一件很奇怪的事情就是不管是本地还是自己上传数据到OJ测试都远远没有到达时限。

本题做法

设$f_i$表示权值为$i$的二叉树的个数,因为一棵二叉树可以通过左右儿子构建起来转移,我们可以得到转移:

$$f_w = \sum_{x, y, w - (x + y) \in c} f_x * f_y$$

注意到左右子树可以为空,所以$f_0 = 1$。

很容易发现这是一个卷积的形式,我们尝试把它写得好看一点。

先把物品写成生成函数的形式,记

$$G(x) = \sum_{i = 0}^{m}[i \in c]x^i$$

题目保证了$G(0) = 0$。

再用$F(x)$表示权值为$x$的二叉树的个数,有

$$F(n) = \sum_{i = 1}^{n}G(i)\sum_{j = 1}^{n - i}F(j)F(n - i - j)$$

$$F(n) = (G * F ^ 2)(n)$$

发现多项式$F$除了第$0$项每一项都可以由上面这个式子得到,而$F(0) = 1$。

得到

$$F = G * F ^ 2 + 1$$

解一元二次方程,

$$F = \frac{2}{1 \pm \sqrt{1 - 4G}}$$

考虑到$G(0) = 0$,$F(0) = 1$,所以取加号。

剩下就是怎么开根的问题。

多项式开根

假设已经求出了$F_0(x)$使$G(F_0(x)) \equiv 0 (\mod x^{\left \lceil \frac{n}{2} \right \rceil})$成立,要求$F(x)$使$G(F(x)) \equiv 0 (\mod x^n)$成立。

在多项式$exp$那里已经提过了这里$G(F(x)) = F(x)^2 - A(x)$。

牛顿迭代的式子拿出来,

$$F(x) \equiv F_0(x) - \frac{G(F_0(x))}{G'(F_0(x))}( \mod x^n)$$

$$G'(F(x)) = 2F(x)$$

代进去

$$F(x) \equiv \frac{F_0(x)^2 + A(x)}{2F_0(x)}(\mod x^n)$$

可以递归计算了。

$$T(n) = T(\frac{n}{2}) + O(nlogn)$$

时间复杂度还是$O(nlogn)$,常数极大就是了。

Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll; const int N = << ; int n, m, a[N];
ll f[N], g[N]; namespace Poly {
const int L = << ;
const ll P = 998244353LL; int lim, pos[L];
ll f[L], g[L], h[L], tmp[L]; inline ll fpow(ll x, ll y) {
ll res = ;
for (x %= P; y > ; y >>= ) {
if (y & ) res = res * x % P;
x = x * x % P;
}
return res;
} const ll inv2 = fpow(, P - ); inline void prework(int len) {
int l = ;
for (lim = ; lim < len; lim <<= , ++l);
for (int i = ; i < lim; i++)
pos[i] = (pos[i >> ] >> ) | ((i & ) << (l - ));
} inline void ntt(ll *c, int opt) {
for (int i = ; i < lim; i++)
if (i < pos[i]) swap(c[i], c[pos[i]]);
for (int i = ; i < lim; i <<= ) {
ll wn = fpow(, (P - ) / (i << ));
if (opt == -) wn = fpow(wn, P - );
for (int len = i << , j = ; j < lim; j += len) {
ll w = ;
for (int k = ; k < i; k++, w = w * wn % P) {
ll x = c[j + k], y = w * c[j + k + i] % P;
c[j + k] = (x + y) % P, c[j + k + i] = (x - y + P) % P;
}
}
} if (opt == -) {
ll inv = fpow(lim, P - );
for (int i = ; i < lim; i++) c[i] = c[i] * inv % P;
}
} void inv(ll *a, ll *b, int len) {
if (len == ) {
b[] = fpow(a[], P - );
return;
} inv(a, b, (len + ) >> );
prework(len << );
for (int i = ; i < lim; i++) f[i] = g[i] = ;
for (int i = ; i < len; i++) f[i] = a[i], g[i] = b[i];
ntt(f, ), ntt(g, );
for (int i = ; i < lim; i++)
g[i] = g[i] * (2LL - g[i] * f[i] % P + P) % P;
ntt(g, -); for (int i = ; i < len; i++) b[i] = g[i];
} inline void direv(ll *c, int len) {
for (int i = ; i < len - ; i++) c[i] = c[i + ] * (i + ) % P;
c[len - ] = ;
} inline void integ(ll *c, int len) {
for (int i = len - ; i > ; i--) c[i] = c[i - ] * fpow(i, P - ) % P;
c[] = ;
} inline void ln(ll *a, ll *b, int len) {
for (int i = ; i < len; i++) h[i] = ;
inv(a, h, len); for (int i = ; i < len; i++) b[i] = a[i];
direv(b, len); prework(len << );
ntt(h, ), ntt(b, );
for (int i = ; i < lim; i++) b[i] = b[i] * h[i] % P;
ntt(b, -); integ(b, len);
} ll F[L], G[L], H[L];
void exp(ll *a, ll *b, int len) {
if (len == ) {
b[] = ;
return;
}
exp(a, b, (len + ) >> ); ln(b, F, len);
F[] = (a[] % P + - F[] + P) % P;
for (int i = ; i < len; i++) F[i] = (a[i] - F[i] + P) % P; prework(len << );
for (int i = len; i < lim; i++) F[i] = ;
for (int i = ; i < lim; i++) G[i] = ;
for (int i = ; i < len; i++) G[i] = b[i];
ntt(F, ), ntt(G, );
for (int i = ; i < lim; i++) F[i] = F[i] * G[i] % P;
ntt(F, -); for (int i = ; i < len; i++) b[i] = F[i];
} void sqr(ll *a, ll *b, int len) {
if (len == ) {
b[] = a[];
return;
} sqr(a, b, (len + ) >> ); for (int i = ; i < len; i++) H[i] = ;
inv(b, H, len); prework(len << );
for (int i = ; i < lim; i++) F[i] = G[i] = ;
for (int i = ; i < len; i++) F[i] = a[i], G[i] = b[i];
ntt(F, ), ntt(G, ), ntt(H, );
for (int i = ; i < lim; i++)
F[i] = (G[i] * G[i] % P + F[i] + P) % P * inv2 % P * H[i] % P;
ntt(F, -); for (int i = ; i < len; i++) b[i] = F[i];
} }; using Poly :: fpow;
using Poly :: P; /* template <typename T>
inline void read(T &X) {
X = 0; char ch = 0; T op = 1;
for (; ch > '9'|| ch < '0'; ch = getchar())
if (ch == '-') op = -1;
for (; ch >= '0' && ch <= '9'; ch = getchar())
X = (X << 3) + (X << 1) + ch - 48;
X *= op;
} */ namespace Fread {
const int L = << ; char buffer[L], *S, *T; inline char Getchar() {
if(S == T) {
T = (S = buffer) + fread(buffer, , L, stdin);
if(S == T) return EOF;
}
return *S++;
} template <class T>
inline void read(T &X) {
char ch; T op = ;
for(ch = Getchar(); ch > '' || ch < ''; ch = Getchar())
if(ch == '-') op = -;
for(X = ; ch >= '' && ch <= ''; ch = Getchar())
X = (X << ) + (X << ) + ch - '';
X *= op;
} } using namespace Fread; namespace Fwrite {
const int L = 2e6 + ; int bufp = ;
char buf[L]; template <typename T>
inline void write(T x) {
if(!x) buf[++bufp] = ''; if(x < ) {
buf[++bufp] = '-';
x = -x;
}
int st[], tp = ;
for(; x; x /= ) st[++tp] = x % ;
for(; tp; tp--) buf[++bufp] = (st[tp] + '');
buf[++bufp] = '\n';
} } using namespace Fwrite; template <typename T>
inline void inc(T &x, T y) {
x += y;
if (x >= P) x -= P;
} template <typename T>
inline void sub(T &x, T y) {
x -= y;
if (x < ) x += P;
} int main() {
/* #ifndef ONLINE_JUDGE
freopen("Sample.txt", "r", stdin);
#endif */ // freopen("3625.in", "r", stdin);
// freopen("3625.out", "w", stdout); read(n), read(m);
for (int x, i = ; i <= n; i++) {
read(x);
if (x <= m) g[x] = ;
} /* for (int i = 0; i <= m; i++)
printf("%lld%c", g[i], " \n"[i == m]); */ g[] = ;
for (int i = ; i <= m; i++) g[i] = (P - 4LL * g[i] % P) % P;
Poly :: sqr(g, f, m + ); /* for (int i = 0; i <= m; i++)
printf("%lld%c", g[i], " \n"[i == m]); for (int i = 0; i <= m; i++)
printf("%lld%c", f[i], " \n"[i == m]); */ inc(f[], 1LL);
for (int i = ; i <= m; i++) g[i] = ;
Poly :: inv(f, g, m + ); /* for (int i = 0; i <= m; i++)
printf("%lld%c", f[i], " \n"[i == m]); */ for (int i = ; i <= m; i++) {
// write(g[i] * 2LL % P);
// printf("\n");
printf("%lld\n", (g[i] + g[i]) % P);
} // fwrite(buf + 1, 1, bufp, stdout);
return ;
}

CF 438E The Child and Binary Tree的更多相关文章

  1. 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 ...

  2. 【CF】438E. The Child and Binary Tree

    http://codeforces.com/contest/438/problem/E 题意:询问每个点权值在 $c_1, c_2, ..., c_m$ 中,总权值和为 $s$ 的二叉树个数.请给出每 ...

  3. Codeforces 438E The Child and Binary Tree - 生成函数 - 多项式

    题目传送门 传送点I 传送点II 传送点III 题目大意 每个点的权值$c\in {c_{1}, c_{2}, \cdots, c_{n}}$,问对于每个$1\leqslant s\leqslant ...

  4. Codeforces 438E. The Child and Binary Tree 多项式,FFT

    原文链接www.cnblogs.com/zhouzhendong/p/CF438E.html 前言 没做过多项式题,来一道入门题试试刀. 题解 设 $a_i$ 表示节点权值和为 $i$ 的二叉树个数, ...

  5. Codeforces 438E The Child and Binary Tree [DP,生成函数,NTT]

    洛谷 Codeforces 思路 看到计数和\(998244353\),可以感觉到这是一个DP+生成函数+NTT的题. 设\(s_i\)表示\(i\)是否在集合中,\(A\)为\(s\)的生成函数,即 ...

  6. Codeforces 250 E. The Child and Binary Tree [多项式开根 生成函数]

    CF Round250 E. The Child and Binary Tree 题意:n种权值集合C, 求点权值和为1...m的二叉树的个数, 形态不同的二叉树不同. 也就是说:不带标号,孩子有序 ...

  7. 【CF438E】The Child and Binary Tree(多项式运算,生成函数)

    [CF438E]The Child and Binary Tree(多项式运算,生成函数) 题面 有一个大小为\(n\)的集合\(S\) 问所有点权都在集合中,并且点权之和分别为\([0,m]\)的二 ...

  8. [codeforces438E]The Child and Binary Tree

    [codeforces438E]The Child and Binary Tree 试题描述 Our child likes computer science very much, especiall ...

  9. [题解] CF438E The Child and Binary Tree

    CF438E The Child and Binary Tree Description 给一个大小为\(n\)的序列\(C\),保证\(C\)中每个元素各不相同,现在你要统计点权全在\(C\)中,且 ...

随机推荐

  1. Jquery each循环中中断

    在each代码块内不能使用break和continue,要实现break和continue的功能的话,要使用其它的方式 break----用return false; continue --用retu ...

  2. HTML5的LocalStorage和sessionStorage的使用

    本文转载自:http://www.cnblogs.com/qiutianlidehanxing-blog/p/5953746.html html5中的Web Storage包括了两种存储方式:sess ...

  3. (转)SQL server 2005查询数据库表的数量和表的数据量

    本文转载自:http://hi.baidu.com/ajyajyajy/item/4e2a7f4dc83393d2c1a592c1 use DBNAMEgoselect * from sysobjec ...

  4. (转)将rdlc报表作为资源嵌套使用

    本文转载自:http://www.cnblogs.com/chenxizhang/archive/2009/05/16/1458469.html 如果我们准备在Windows Forms里面使用rdl ...

  5. Python文件操作,with open as追加文本内容实例

    最常见的读写操作 import re with open('/Users/Mr.Long/Desktop/data.txt', 'w') as f: f.write('hello world') 就这 ...

  6. WindowsPhone自定义控件详解(二) - 模板类库分析

    转自:http://blog.csdn.net/mr_raptor/article/details/7251948 WindowsPhone自定义控件详解(一) - 控件类库分析 上一节主要分析了控件 ...

  7. 在Centos中导入sql文件的方法

    在Centos中导入sql文件的方法 利用mysql -u root -p进入mysql数据库 对于文件的导入,在Centos下里面的是首先要新建一个和文件相同名字的数据库.例如:mysql>c ...

  8. 【BZOJ】2342: [Shoi2011]双倍回文(Manacher)

    题目 传送门:QWQ 分析 (sb如我写了发不知道什么东西在洛谷上竟然水了84分 嗯咳 设$ i $为双重回文的中心 如果$ j~i $ 可以被算作答案,只有满足如下两式: $ p[j]+j \geq ...

  9. django No migrations to apply 问题解决

    最近在用django写项目,有的时候字段不够用,需要models增加字段,但是想回滚或者修改或者修改了属性等,例如忘了添加meta table于是操作了migrations 导致makemigrati ...

  10. OD 实验(十七) - 对一个程序的逆向分析

    程序: 运行程序 弹出一个对话框,点击 OK 来到主界面,点击 Help -> Register Now 这是输入注册码的地方 按关闭程序的按钮 会提示剩下 30 天的使用时间 用 Ressco ...