题意:点分治每次随机选重心,求期望复杂度。

发现一次点分治的复杂度就是点分树上每个节点的子树大小之和。(并没有发现......)

这个

注意这个写法有问题,随便来个菊花图就是n2了。

每一层点分治的时候,时间复杂度决不能与上一层大小挂钩。

 /**************************************************************
Problem: 3451
Language: C++
Result: Accepted
Time:5548 ms
Memory:8548 kb
****************************************************************/ #include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath> typedef long long LL;
typedef long double LD;
const LD pi = 3.1415926535897932384626;
const int N = , INF = 0x3f3f3f3f; inline void read(int &x) {
x = ;
char c = getchar();
while(c < '' || c > '') {
c = getchar();
}
while(c >= '' && c <= '') {
x = (x << ) + (x << ) + c - ;
c = getchar();
}
return;
} struct cp {
LD x, y;
cp(LD X = , LD Y = ) {
x = X;
y = Y;
}
inline cp operator +(const cp &w) const {
return cp(x + w.x, y + w.y);
}
inline cp operator -(const cp &w) const {
return cp(x - w.x, y - w.y);
}
inline cp operator *(const cp &w) const {
return cp(x * w.x - y * w.y, x * w.y + y * w.x);
}
}a[N * ], b[N * ]; struct Edge {
int nex, v;
}edge[N << ]; int tp; int r[N * ], n, e[N], small, root, d[N], bin[N], cnt[N], _n, siz[N];
bool del[N]; inline void add(int x, int y) {
tp++;
edge[tp].v = y;
edge[tp].nex = e[x];
e[x] = tp;
return;
} inline void FFT(cp *a, int n, int f) {
for(register int i = ; i < n; i++) {
if(i < r[i]) {
std::swap(a[i], a[r[i]]);
}
}
for(register int len = ; len < n; len <<= ) {
cp Wn(cos(pi / len), f * sin(pi / len));
for(register int i = ; i < n; i += (len << )) {
cp w(, );
for(register int j = ; j < len; j++) {
cp t = a[i + len + j] * w;
a[i + len + j] = a[i + j] - t;
a[i + j] = a[i + j] + t;
w = w * Wn;
}
}
}
if(f == -) {
for(register int i = ; i <= n; i++) {
a[i].x /= n;
}
}
return;
} inline void cal(int n, int f) {
/*printf("cal \n");
for(int i = 0; i <= n; i++) {
printf("%d ", bin[i]);
}
printf("\n");*/
int lm = , len = ;
while(len <= n * ) {
len <<= ;
lm++;
}
for(register int i = ; i <= len; i++) {
r[i] = (r[i >> ] >> ) | ((i & ) << (lm - ));
}
for(register int i = ; i <= n; i++) {
a[i] = cp(bin[i], );
}
for(register int i = n + ; i <= len; i++) {
a[i] = cp(, );
}
FFT(a, len, );
for(register int i = ; i <= len; i++) {
a[i] = a[i] * a[i];
}
FFT(a, len, -);
/*for(int i = 0; i <= n + n; i++) {
printf("%d ", (int)(a[i].x + 0.5));
}
printf("\n");*/
for(register int i = ; i <= len; i++) {
cnt[i] += f * (int)(a[i].x + 0.5);
}
return;
} void get_root(int x, int f) {
bin[d[x]]++;
siz[x] = ;
int large = -;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == f || del[y]) {
continue;
}
get_root(y, x);
siz[x] += siz[y];
large = std::max(large, siz[y]);
}
if(small > std::max(large, _n - siz[x])) {
small = std::max(large, _n - siz[x]);
root = x;
}
return;
} void DFS(int x, int f) {
d[x] = d[f] + ;
bin[d[x]]++;
siz[x] = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == f || del[y]) {
continue;
}
DFS(y, x);
siz[x] += siz[y];
}
return;
} void div(int x, int f, int last_n) {
if(f) {
memset(bin, , sizeof(int) * (last_n + ));
}
small = INF;
get_root(x, );
if(f) {
cal(last_n, -);
}
x = root;
memset(bin, , sizeof(int) * (_n + ));
DFS(x, );
cal(_n, );
del[x] = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(del[y]) {
continue;
}
_n = siz[y];
div(y, , siz[x]);
}
return;
} int main() {
d[] = -;
read(n);
for(register int i = , x, y; i < n; i++) {
read(x); read(y);
add(x + , y + ); add(y + , x + );
} _n = n;
div(, , n);
LD ans = ;
/*for(int i = 0; i <= n; i++) {
printf("%d ", cnt[i]);
}
printf("\n");*/
for(register int i = ; i < n; i++) {
ans += (LD)cnt[i] / (i + );
}
printf("%.4Lf\n", ans);
return ;
}

AC代码

注意FFT里面j从0开始,到len。

bzoj3451 Normal的更多相关文章

  1. [BZOJ3451]normal 点分治,NTT

    [BZOJ3451]normal 点分治,NTT 好久没更博了,咕咕咕. BZOJ3451权限题,上darkbzoj交吧. 一句话题意,求随机点分治的期望复杂度. 考虑计算每个点对的贡献:如果一个点在 ...

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

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

  3. BZOJ3451 Normal 期望、点分治、NTT

    BZOJCH传送门 题目大意:给出一棵树,求对其进行随机点分治的复杂度期望 可以知道一个点的贡献就是其点分树上的深度,也就是这个点在点分树上的祖先数量+1. 根据期望的线性性,考虑一个点对\((x,y ...

  4. 【BZOJ3451】Normal

    [BZOJ3451]Normal Description 某天WJMZBMR学习了一个神奇的算法:树的点分治! 这个算法的核心是这样的: 消耗时间=0 Solve(树 a) 消耗时间 += a 的 大 ...

  5. 【BZOJ3451】Normal (点分治)

    [BZOJ3451]Normal (点分治) 题面 BZOJ 题解 显然考虑每个点的贡献.但是发现似乎怎么算都不好计算其在点分树上的深度. 那么考虑一下这个点在点分树中每一次被计算的情况,显然就是其在 ...

  6. 【BZOJ3451】Tyvj1953 Normal 点分治+FFT+期望

    [BZOJ3451]Tyvj1953 Normal Description 某天WJMZBMR学习了一个神奇的算法:树的点分治!这个算法的核心是这样的:消耗时间=0Solve(树 a) 消耗时间 += ...

  7. BZOJ3451: Tyvj1953 Normal

    题解: 好神的一道题.蒟蒻只能膜拜题解. 考虑a对b的贡献,如果a是a-b路径上第一个删除的点,那么给b贡献1. 所以转化之后就是求sigma(1/dist(i,j)),orz!!! 如果不是分母的话 ...

  8. BZOJ3451 Tyvj1953 Normal 点分治 多项式 FFT

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3451.html 题目传送门 - BZOJ3451 题意 给定一棵有 $n$ 个节点的树,在树上随机点分 ...

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

    https://www.cnblogs.com/GXZlegend/p/8611948.html #include<cmath> #include<cstdio> #inclu ...

随机推荐

  1. 做完小程序项目、老板给我加了5k薪资~

    大家好,我是苏南,今天要给大家分享的是最近公司做的一个小程序项目,过程中的一些好的总结和遇到的坑,希望能给其他攻城狮带来些许便利,更希望能做完之后老板给你加薪- 今天是中秋节的第一天,假日的清晨莫名的 ...

  2. 树的最长链-POJ 1985 树的直径(最长链)+牛客小白月赛6-桃花

    求树直径的方法在此转载一下大佬们的分析: 可以随便选择一个点开始进行bfs或者dfs,从而找到离该点最远的那个点(可以证明,离树上任意一点最远的点一定是树的某条直径的两端点之一:树的直径:树上的最长简 ...

  3. Pair_Work Project

    结对项目小记 ——by    12061227 康    12061179 宇帆 结对编程就是一种敏捷软件开发的方法,两个人在一个计算机上共同工作.一个人输入,而另一个人检查他输入的每一行代码.输入代 ...

  4. Redis学习笔记之多机数据库

    1.复制 完整重同步,从服务器完全复制主服务器的数据,主要通过RDB文件和单条命令传输(套接字连接). 部分重同步,主服务器进行命令传播的时候,不仅会把写命令发送给从服务器,而且还会把写命令放入复制积 ...

  5. 《Linux内核分析》第五周学习笔记

    <Linux内核分析>第五周学习笔记 扒开系统调用的三层皮(下) 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.c ...

  6. 20135337——Linux实践三:ELF文件格式(64位系统,简单分析)

    ELF文件格式简单分析 (具体分析见上一篇ELF文件格式32位系统) ELF-header 第一行: 457f 464c :魔数: 0201 :64位系统,小端法 01 :文件头版本 剩余默认0: 第 ...

  7. 2丶利用NABCD模型进行竞争性需求分析

    确定项目:公交查询系统 分析小组:在路上 选择比努力更重要.一个项目成功自然离不开组员们的努力.但是,光努力是不够的.还需要用户有需求,能快速实现. 这些东西,看似很虚,却能让我们少走不少弯路.做项目 ...

  8. beta(3/7)

    团队信息 队名:爸爸饿了 组长博客:here 作业博客:here 组员情况 组员1(组长):王彬 过去两天完成了哪些任务 协助后端完成历史记录接口.美食排行榜接口 完成食堂平面图的绘制 确定web端业 ...

  9. MySQLi面向对象实践--select

    对于update.insert.delete请参考http://www.cnblogs.com/-beyond/p/8457580.html 执行select,如果SQL语句执行成功,那么返回的是一个 ...

  10. shell脚本--cut命令与awk简单使用

    cut:对内容进行列切割 -d 后面的是分割符,表示用什么符号来分割符来分割列,分隔符使用引号括起来: -f后面跟着要选择的字段列,从1开始,表示第一列,如果要多列,可以用逗号分隔 : -c参数后面跟 ...