「BZOJ 3645」小朋友与二叉树

解题思路

令 \(G(x)\) 为关于可选大小集合的生成函数,即

\[G(x)=\sum[i\in c ] x^i
\]

令 \(F(x)\) 第 \(n\) 项的系数为为权值为 \(n\) 的二叉树的方案数,显然有

\[F(x)=F(x)^2G(x)+1\\
F^2(x)G(x)-F(x)+1=0 \\
F(x)=\dfrac{1\pm\sqrt{1-4G(x)}}{2G(x)}
\]

当 \(x\to 0\) 时,\(F(x)\) 的值为 \(1\) ,当取加号的时候发现

\[\lim_{x\to0} F(x)=\dfrac{1}{G(x)} \\ =\infty
\]

所以

\[F(x)=\dfrac{1-\sqrt{1-4G(x)}}{2G(x)}
\]

由于 \(2G(x)\) 的常数项为 \(0\) 不存在逆元,所以要稍作一些变化

\[F(x)=\dfrac{4G(x)}{2G(x)(1+\sqrt{1-4G(x)})} \\
=\dfrac{2}{1+\sqrt{1-4G(x)}}
\]

\(\sqrt{1-4G(x)}\) 的常数项为 \(1\) ,一遍开根一遍求逆就好了,复杂度 \(\mathcal O(n\log n)\) ,下面代码拖了多项式板子所以有用不到的部分。

code

/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = (1 << 22) + 5, P = 998244353, G = 3;
namespace poly{
int rev[N], W[N], invW[N], len, lg;
inline int Pow(int a, int b){
int ans = 1;
for(; b; b >>= 1, a = 1ll * a * a % P)
if(b & 1) ans = 1ll * ans * a % P;
return ans;
}
inline void init(){
for(int k = 2; k < N; k <<= 1)
W[k] = Pow(G, (P - 1) / k), invW[k] = Pow(W[k], P - 2);
}
inline void timesinit(int lenth){
for(len = 1, lg = 0; len <= lenth; len <<= 1, lg++);
for(int i = 0; i < len; i++)
rev[i] = (rev[i>>1] >> 1) | ((i & 1) << (lg - 1));
}
inline void DFT(int *a, int sgn){
for(int i = 0; i < len; i++) if(i < rev[i]) swap(a[i], a[rev[i]]);
for(int k = 2; k <= len; k <<= 1){
int w = ~sgn ? W[k] : invW[k];
for(int i = 0; i < len; i += k){
int now = 1;
for(int j = i; j < i + (k >> 1); j++){
int x = a[j], y = 1ll * a[j+(k>>1)] * now % P;
a[j] = (x + y) % P, a[j+(k>>1)] = (x - y + P) % P;
now = 1ll * now * w % P;
}
}
}
if(sgn == -1){
int Inv = Pow(len, P - 2);
for(int i = 0; i < len; i++) a[i] = 1ll * a[i] * Inv % P;
}
}
inline void getinv(int *a, int *b, int n){
static int tmp[N];
if(n == 1) return (void) (b[0] = Pow(a[0], P - 2));
getinv(a, b, (n + 1) / 2);
timesinit(n * 2 - 1);
for(int i = 0; i < len; i++) tmp[i] = i < n ? a[i] : 0;
DFT(tmp, 1), DFT(b, 1);
for(int i = 0; i < len; i++)
b[i] = 1ll * (2 - 1ll * tmp[i] * b[i] % P + P) % P * b[i] % P;
DFT(b, -1);
for(int i = n; i < len; i++) b[i] = 0;
for(int i = 0; i < len; i++) tmp[i] = 0;
}
inline void getsqrt(int *a, int *b, int n){
static int tmp1[N], tmp2[N];
if(n == 1) return (void) (b[0] = 1);
getsqrt(a, b, (n + 1) / 2);
for(int i = 0; i < n; i++) tmp1[i] = a[i];
getinv(b, tmp2, n), timesinit(n * 2 - 1);
DFT(tmp1, 1), DFT(tmp2, 1);
for(int i = 0; i < len; i++) tmp1[i] = 1ll * tmp1[i] * tmp2[i] % P;
DFT(tmp1, -1);
for(int i = 0; i < len; i++)
b[i] = 1ll * (b[i] + tmp1[i]) % P * Pow(2, P - 2) % P;
for(int i = n; i < len; i++) b[i] = 0;
for(int i = 0; i < len; i++) tmp1[i] = tmp2[i] = 0;
}
inline void getln(int *a, int *b, int n){
static int tmp[N];
getinv(a, b, n), timesinit(n * 2 - 1);
for(int i = 1; i < n; i++) tmp[i-1] = 1ll * a[i] * i % P;
DFT(tmp, 1), DFT(b, 1);
for(int i = 0; i < len; i++) b[i] = 1ll * tmp[i] * b[i] % P;
DFT(b, -1);
for(int i = len - 1; i; i--) b[i] = 1ll * b[i-1] * Pow(i, P - 2) % P;
b[0] = 0;
for(int i = n; i < len; i++) b[i] = 0;
for(int i = 0; i < len; i++) tmp[i] = 0;
}
inline void getexp(int *a, int *b, int n){
static int tmp[N];
if(n == 1) return (void) (b[0] = 1);
getexp(a, b, (n + 1) / 2);
getln(b, tmp, n), timesinit(n * 2 - 1);
for(int i = 0; i < n; i++) tmp[i] = (!i - tmp[i] + a[i] + P) % P;
DFT(tmp, 1), DFT(b, 1);
for(int i = 0; i < len; i++) b[i] = 1ll * b[i] * tmp[i] % P;
DFT(b, -1);
for(int i = n; i < len; i++) b[i] = 0;
for(int i = 0; i < len; i++) tmp[i] = 0;
}
inline void power(int *a, int *b, int n, int m, ll k){
static int tmp[N];
for(int i = 0; i < m; i++) b[i] = 0;
int fir = -1;
for(int i = 0; i < n; i++) if(a[i]){ fir = i; break; }
if(fir && k >= m) return;
if(fir == -1 || 1ll * fir * k >= m) return;
for(int i = fir; i < n; i++) b[i-fir] = a[i];
for(int i = 0; i < n - fir; i++)
b[i] = 1ll * b[i] * Pow(a[fir], P - 2) % P;
getln(b, tmp, m);
for(int i = 0; i < m; i++)
b[i] = 1ll * tmp[i] * (k % P) % P, tmp[i] = 0;
getexp(b, tmp, m);
for(int i = m; i >= fir * k; i--)
b[i] = 1ll * tmp[i-fir*k] * Pow(a[fir], k % (P - 1)) % P;
for(int i = 0; i < fir * k; i++) b[i] = 0;
for(int i = 0; i < m; i++) tmp[i] = 0;
}
}
using poly::Pow;
using poly::DFT;
using poly::timesinit;
int a[N], b[N], c[N], n, m;
int main(){
poly::init(), read(n), read(m), m++;
for(int i = 1, x; i <= n; i++)
read(x), a[x] = P - 4;
a[0]++, poly::getsqrt(a, b, m);
b[0] = (b[0] + 1) % P;
poly::getinv(b, c, m);
for(int i = 1; i < m; i++) printf("%lld\n", 2ll * c[i] % P);
return 0;
}

「BZOJ 3645」小朋友与二叉树的更多相关文章

  1. 「BZOJ 4228」Tibbar的后花园

    「BZOJ 4228」Tibbar的后花园 Please contact lydsy2012@163.com! 警告 解题思路 可以证明最终的图中所有点的度数都 \(< 3\) ,且不存在环长是 ...

  2. 「BZOJ 4502」串

    「BZOJ 4502」串 题目描述 兔子们在玩字符串的游戏.首先,它们拿出了一个字符串集合 \(S\),然后它们定义一个字符串为"好"的,当且仅当它可以被分成非空的两段,其中每一段 ...

  3. 「BZOJ 4289」 PA2012 Tax

    「BZOJ 4289」 PA2012 Tax 题目描述 给出一个 \(N\) 个点 \(M\) 条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点 \(1\) 到点 \( ...

  4. 「BZOJ 2534」 L - gap字符串

    「BZOJ 2534」 L - gap字符串 题目描述 有一种形如 \(uv u\) 形式的字符串,其中 \(u\) 是非空字符串,且 \(v\) 的长度正好为 \(L\), 那么称这个字符串为 \( ...

  5. 「BZOJ 2956」模积和

    「BZOJ 2956」模积和 令 \(l=\min(n,m)\).这个 \(i\neq j\) 非常不优雅,所以我们考虑分开计算,即: \[\begin{aligned} &\sum_{i=1 ...

  6. Solution -「BZOJ 3812」主旋律

    \(\mathcal{Description}\)   Link.   给定含 \(n\) 个点 \(m\) 条边的简单有向图 \(G=(V,E)\),求 \(H=(V,E'\subseteq E)\ ...

  7. 「BZOJ 1001」狼抓兔子

    题目链接 luogu bzoj \(Solution\) 这个貌似没有什么好讲的吧,直接按照这个给的图建图就好了啊,没有什么脑子,但是几点要注意的: 建双向边啊. 要这么写,中间还要写一个\(whil ...

  8. 「BZOJ 5188」「Usaco2018 Jan」MooTube

    题目链接 luogu bzoj \(Describe\) 有一个\(n\)个节点的树,边有权值,定义两个节点之间的距离为两点之间的路径上的最小边权 给你\(Q\)个询问,问你与点\(v\)的距离大于等 ...

  9. 「BZOJ 1791」「IOI 2008」Island「基环树」

    题意 求基环树森林所有基环树的直径之和 题解 考虑的一个基环树的直径,只会有两种情况,第一种是某个环上结点子树的直径,第二种是从两个环上结点子树内的最深路径,加上环上这两个结点之间的较长路径. 那就找 ...

随机推荐

  1. 鸟哥的Linux私房菜——第十五章:正规表示法

    视频链接 B站:http://www.bilibili.com/video/av10364761/ 目录如下 1. 前言:2. 基础正规表示法:2.1 以 grep 撷取字符串 (grep -iv   ...

  2. Nested Loops(嵌套循环)

    先扫描驱动表的(外表),外表的每一行驱动内表,然后匹配,所以nest loops不是主要依赖于内表有多少行,而是非常依赖于驱动表到底有多少行参与nested loops,因为驱动表(或者准确的说是驱动 ...

  3. JMS之——ActiveMQ时抛出的错误Could not connect to broker URL-使用线程池解决高并发连接

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/69046395 解决使用activemq时抛出的异常:javax.j ms.JMSE ...

  4. bzoj千题计划232:bzoj4727: [POI2017]Turysta

    http://www.lydsy.com/JudgeOnline/problem.php?id=4727 竞赛图tarjan缩点后得到的拓扑图一定是一条链 因为竞赛图任意两点的前后顺序确定,只有一种拓 ...

  5. spring框架学习(二)使用注解代替xml配置

    注解 1.使用注解配置spring 1)开启使用注解代理配置文件 <?xml version="1.0" encoding="UTF-8"?> &l ...

  6. 5个经典的javascript面试问题

    问题1:Scope作用范围 考虑下面的代码: (function() {   var a = b = 5;})(); console.log(b); 什么会被打印在控制台上? 回答 上面的代码会打印 ...

  7. CS229 笔记08

    CS229 笔记08 Kernel 回顾之前的优化问题 原始问题为: \[ \min_{w,b} \frac{1}{2}||w||^2\\[1.5em] {\text{s.t.}}y^{(i)}\le ...

  8. 如何教会老婆写 Python ?

    什么是code? code就就是一种语言,一种计算机能读懂的语言.计算机是一个傻逼,他理解不了默认两可的任何东西. 比如,你让你老公去买个西瓜,你老公会自己决定去哪里买,买几个,找个搞活动打折的买,总 ...

  9. 记webpack下提取公共js代码的方法

    环境: webpack4.6 + html-webpack-plugin 多页面多入口 经多次研究,稍微靠谱可用的配置 optimization: { splitChunks: { minSize: ...

  10. Dream------Hadoop--网络拓扑与Hadoop--摘抄

    两个节点在一个本地网络中被称为“彼此的近邻”是什么意思?在高容量数据处理中,限制因素是我们在节点间 传送数据的速率-----带宽很稀缺.这个想法便是将两个节点间的带宽作为距离的衡量标准.   衡量节点 ...