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. 18.9.10 LeetCode刷题笔记

    本人算法还是比较菜的,因此大部分在刷基础题,高手勿喷 选择Python进行刷题,因为坑少,所以不太想用CPP: 1.买股票的最佳时期2 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. ...

  2. kali openvas安装

    最新的kali需要用apt-get安装后使用 安装 apt-get install openvas 自动设置 openvas-setup 检测设置 openvas-check-setup 如果检测没有 ...

  3. Synergy CORTEX M 启动流程

    1.启动文件“startup_S7G2.c” 中断向量表地址指针:“0xe000ed08” /* Vector table. */ BSP_DONT_REMOVE const exc_ptr_t __ ...

  4. erlang的一些小技巧(不定期更新)

    在任意节点热更新代码 rpc:call(Node,c,l,[Mod]) c和l的指的是code,library Erlang Shell隐藏的小技巧 f(). %%把所有绑定变量释放掉 f(Val). ...

  5. cocos2d-js 3.0 ios平台编译打包

    原帖在http://www.cocoachina.com/bbs/read.php?tid=209356 整理到github的https://github.com/faint2death/cocos2 ...

  6. js实现定时调用的函数setInterval()

    setInterval是一个实现定时调用的函数,可按照指定的周期(以毫秒计)来调用函数或计算表达式.setInterval方法会不停地调用函数,直到 clearInterval被调用或窗口被关闭 定义 ...

  7. GOF23设计模式之外观模式(facade)

    一.外观模式概述 外观模式也称为门面模式. 核心:为了系统提供统一的入口,封装子系统的复杂性,便于客户端调用. 二.外观模式场景导入与示例代码 场景:要想自己去注册一个公司,首先去工商局检测命名是否合 ...

  8. android视频处理相关资料

    <开源>基于Android的点对点视频通信/RTSP/RTP/H.264 http://blog.csdn.net/cazicaquw/article/details/8650543 历经 ...

  9. MySql——编程

    基本语法形式 语句块模式: 在mysql编程中,begin....end;基本代替了原来编程语句中的{...}语法. 但又有所区别: 一个bigin...end;块,可以给定一个“标识符”,并且可以使 ...

  10. java后台获取URL带参demo

    URL:http://aos.wall.youmi.net/v2/check_fb_sig?order=YM130402cygr_UTb42&app=30996ced018a2a5e& ...