[BZOJ3451]normal 点分治,NTT

好久没更博了,咕咕咕。

BZOJ3451权限题,上darkbzoj交吧。

一句话题意,求随机点分治的期望复杂度。

考虑计算每个点对的贡献:如果一个点在点分树上是另一个点的祖先,那么这个点对另一个点的贡献就是1,这样的话,这个点就必须是这两个点之间的链上的点中在点分树上深度最浅的点,由于链上每个点成为点分树上最浅的点的概率都是相等的,所以这个点对对最终的期望的贡献就是\(\frac{1}{dis(i, j) + 1}\),这里的\(dis(i, j)\)习惯上认为是边的条数,\(+1\)就变成了点的个数。现在我们要求的就是\(\sum \limits _{i = 1} ^{n} \sum \limits _{j = 1} ^{n} \frac {1} {dis(i, j) + 1}\)。

考虑怎样在树上统计,明显需要点分治,每次统计从当前分治中心出发的所有长度的路径条数,跟先前统计过的子树合并一下就好了。观察合并的式子,设\(f[i]\)表示这次合并统计的长度为\(i\)的路径条数,\(p[i]\)表示以前统计过的子树中长度为\(i\)的路径条数,\(q[i]\)表示这次统计的长度为\(i\)的路径条数,显然有\(f[k] = \sum \limits _{i + j = k} p[i] * q[j]\),明显是一个卷积的形式,可以FFT,但是发现\(f\)数组的值肯定不会超过NTT模数,于是直接NTT。时间复杂度\(O(n (\log n) ^ 2)\)。

实现的时候要注意,每次从分支中心出发统计时,必须先把子树按深度或大小排一遍序,从小往大处理,不然一个扫把图就能把你卡成\(n ^ 2 \log n\),可以自己画图手玩。

#include <cstdio>
#include <cctype>
#include <vector>
#include <cstring>
#include <algorithm>
#define R register
#define I inline
#define D double
#define L long long
#define B 1000000
using namespace std;
const int N = 32777, P = 998244353, G = 3, H = 332748118;
char buf[B], *p1, *p2;
I char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, B, stdin), p1 == p2) ? EOF : *p1++; }
I int rd() {
R int f = 0;
R char c = gc();
while (c < 48 || c > 57)
c = gc();
while (c > 47 && c < 58)
f = f * 10 + (c ^ 48), c = gc();
return f;
}
int s[N], t[N], v[N], p[N], q[N], a[N], b[N], d[N], c[N], h[N], u, r, S, e, F, M;
D o;
vector <int> g[N];
I int max(int x, int y) { return x > y ? x : y; }
I void swp(int &x, int &y) { x ^= y, y ^= x, x ^= y; }
I int cmp(int x, int y) { return t[x] < t[y]; }
void gsz(int x, int f) {
t[x] = 1;
for (R int i = 0, y; i < s[x]; ++i)
if (!v[y = g[x][i]] && y ^ f)
gsz(y, x), t[x] += t[y];
}
void grt(int x, int f, int a) {
R int m = 0, i, y;
for (i = 0; i < s[x]; ++i)
if (!v[y = g[x][i]] && y ^ f)
m = max(m, t[y]), grt(y, x, a);
m = max(m, a - t[x]);
if (m < u)
u = m, r = x;
}
void dfs(int x, int f, int d) {
c[++e] = d;
for (R int i = 0, y; i < s[x]; ++i)
if (!v[y = g[x][i]] && y ^ f)
dfs(y, x, d + 1);
}
I L pwr(L a, L b) {
L r = 1;
for (; b; b >>= 1, a = a * a % P)
if (b & 1)
r = r * a % P;
return r;
}
void ntt(int *f, int v) {
R int i, j, k, t;
L p, q, o;
for (i = 0; i < M; ++i)
if (i < d[i])
swp(f[i], f[d[i]]);
for (i = 1; i < M; i <<= 1) {
t = i << 1, p = pwr(v ? G : H, (P - 1) / t);
for (j = 0; j < M; j += t)
for (q = 1, k = 0; k < i; ++k)
o = q * f[i + j + k] % P, f[i + j + k] = (f[j + k] - o + P) % P, f[j + k] = (f[j + k] + o + P) % P, q = q * p % P;
}
}
void dac(int x) {
R int i, j, y, z;
p[0] = 1, h[0] = 0, u = S, gsz(x, 0), grt(x, 0, t[x]), v[r] = 1, sort(&g[r][0], s[r] + &g[r][0], cmp);
for (i = 0; i < s[r]; ++i)
if (!v[y = g[r][i]]) {
for (M = 1; M <= t[x]; M <<= 1) {}
e = 0, dfs(y, r, 1), F = pwr(M, P - 2), d[0] = 0;
for (z = M >> 1, j = 0; j < M; ++j)
d[j] = (d[j >> 1] >> 1)|((j & 1) ? z : 0);
for (j = 1; j <= e; ++j)
++q[c[j]], h[++h[0]] = c[j];
memcpy(a, p, M * 4), memcpy(b, q, M * 4);
ntt(a, 1), ntt(b, 1);
for (j = 0; j < M; ++j)
a[j] = 1ll * a[j] * b[j] % P;
ntt(a, 0);
for (j = 0; j < M; ++j)
p[j] += q[j], a[j] = 1ll * a[j] * F * 2 % P, o += (D)a[j] / (j + 1);
for (j = 1; j <= e; ++j)
q[c[j]] = 0;
}
for (i = 1; i <= h[0]; ++i)
p[h[i]] = 0;
for (x = r, i = 0; i < s[x]; ++i)
if(!v[y = g[x][i]])
dac(y);
}
int main() {
R int n = rd(), i, x, y;
for (S = 1; S <= n; S <<= 1) {}
for (i = 1; i < n; ++i)
x = rd() + 1, y = rd() + 1, g[x].push_back(y), g[y].push_back(x);
for (i = 1; i <= n; ++i)
s[i] = g[i].size();
o = n, dac(1), printf("%.4lf", o);
return 0;
}

码风也变了。。。

[BZOJ3451]normal 点分治,NTT的更多相关文章

  1. [BZOJ3451]Normal(点分治+FFT)

    [BZOJ3451]Normal(点分治+FFT) 题面 给你一棵 n个点的树,对这棵树进行随机点分治,每次随机一个点作为分治中心.定义消耗时间为每层分治的子树大小之和,求消耗时间的期望. 分析 根据 ...

  2. #565. 「LibreOJ Round #10」mathematican 的二进制(期望 + 分治NTT)

    题面 戳这里,题意简单易懂. 题解 首先我们发现,操作是可以不考虑顺序的,因为每次操作会加一个 \(1\) ,每次进位会减少一个 \(1\) ,我们就可以考虑最后 \(1\) 的个数(也就是最后的和) ...

  3. LOJ2541 PKUWC2018猎人杀(概率期望+容斥原理+生成函数+分治NTT)

    考虑容斥,枚举一个子集S在1号猎人之后死.显然这个概率是w1/(Σwi+w1) (i∈S).于是我们统计出各种子集和的系数即可,造出一堆形如(-xwi+1)的生成函数,分治NTT卷起来就可以了. #i ...

  4. 【BZOJ-3456】城市规划 CDQ分治 + NTT

    题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=3456 Solution 这个问题可以考虑dp,利用补集思想 N个点的简单图总数量为$2^{ ...

  5. CF960G Bandit Blues 【第一类斯特林数 + 分治NTT】

    题目链接 CF960G 题解 同FJOI2016只不过数据范围变大了 考虑如何预处理第一类斯特林数 性质 \[x^{\overline{n}} = \sum\limits_{i = 0}^{n}\be ...

  6. 洛谷5月月赛T30212 玩游戏 【分治NTT + 多项式求ln】

    题目链接 洛谷T30212 题解 式子很容易推出来,二项式定理展开后对于\(k\)的答案即可化简为如下: \[k!(\sum\limits_{i = 0}^{k} \frac{\sum\limits_ ...

  7. loj2541 「PKUWC2018」猎人杀 【容斥 + 分治NTT】

    题目链接 loj2541 题解 思路很妙啊, 人傻想不到啊 觉得十分难求,考虑容斥 由于\(1\)号可能不是最后一个被杀的,我们容斥一下\(1\)号之后至少有几个没被杀 我们令\(A = \sum\l ...

  8. hdu5279 YJC plays Minecraft 【分治NTT】

    题目链接 hdu5279 题解 给出若干个完全图,然后完全图之间首尾相连并成环,要求删边使得两点之间路径数不超过\(1\),求方案数 容易想到各个完全图是独立的,每个完全图要删成一个森林,其实就是询问 ...

  9. CF960G Bandit Blues 分治+NTT(第一类斯特林数)

    $ \color{#0066ff}{ 题目描述 }$ 给你三个正整数 \(n\),\(a\),\(b\),定义 \(A\) 为一个排列中是前缀最大值的数的个数,定义 \(B\) 为一个排列中是后缀最大 ...

随机推荐

  1. 12.2Data Guard新特性--使用DBMS_DBCOMP.DBCOMP数据比较

          Oracle Data Guard会主动对Hot数据(数据正被读取或修改)执行验证, 无论是primary还是standby,但对于那些Cold数据不会做任何检查和校验.所以在12.2版本 ...

  2. vue的项目

    vue的项目打开也是非常具有解耦性的 最重要的就是src目录了  我们的入口在main中  main是你的实例化vue  app中就是我们的每一块田地是我们的vue实例对这个的操作 ,index因为是 ...

  3. IP地址分类/IP地址10开头和172开头和192开头的区别/判断是否同一网段(A、B、C三类地址)【转】

    简单来说在公司或企业内部看到的就基本都是内网IP,ABC三类IP地址里的常见IP段. 每个IP地址都包含两部分,即网络号和主机号. InterNIC将IP地址分为五类:A类保留给ZF或大型企业,B类分 ...

  4. Linux----CentOS-7搭建免流服务器(iOS 端)

    本次实验采用腾讯云服务器:https://cloud.tencent.com/ 大学生身份的可以看看有没有什么活动购买 其他身份的78一个月 关于腾讯云服务器的使用可以看看腾讯云的使用手册 本博客涉及 ...

  5. Log Structured Merge Trees (LSM)

    1      概念 LSM = Log Structured Merge Trees 来源于google的bigtable论文. 2      解决问题 传统的数据库如MySql采用B+树存放数据,B ...

  6. n=n+1 放在print(s)的上面的影响 (2) n=n=+1在前面,则不满足前面<100条件时候,才跳出while的循环,这时候while循环结束, 到了外面的下一步-->print()

    1+2+3+....+100=     ? n=1 s = 0 while n < =100: s = s+n n= n+1 # n=n+1    在print(s)上面的情况 print(s)

  7. ABAP很厉害是怎么一种体验?

    知乎上偶然看到这个问题,觉得很有意思,我也来回答一发. 我本科和研究生学的是计算机专业,做项目用C/C++,研究生三年项目的代码量大概在三到四万行左右.2007年大学毕业加入SAP成都研究院一直工作到 ...

  8. 起床困难综合症 NOI_2014_D1T1

    这道题的正解其实没什么好说的,反而是部分分设计非常巧妙. 之所以要单开一篇是因为当时机房的部分同学刚学位运算,我拿这个题去讲想毒瘤大家一下,于是做了一个挺好看的课件. ppt -> pdf -& ...

  9. BZOJ3611:[HEOI2014]大工程(树形DP,虚树)

    Description 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道.  我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上.  在 2 个国家 a,b 之间建一条新通 ...

  10. bitMap算法实现以及ckHash函数类,将字符串映射成数字,同时可以将数字映射成字符串

    ckHash函数类,将字符串映射成数字,同时可以将数字映射成字符串 说明 1.所谓的BitMap就是用一个bit位来标记某个元素所对应的value,而key即是该元素,由于BitMap使用了bit位来 ...