题目描述

给你一棵 $n$ 个点的树,对这棵树进行随机点分治,每次随机一个点作为分治中心。定义消耗时间为每层分治的子树大小之和,求消耗时间的期望。

输入

第一行一个整数n,表示树的大小
接下来n-1行每行两个数a,b,表示a和b之间有一条边
注意点是从0开始标号的

输出

一行一个浮点数表示答案
四舍五入到小数点后4位
如果害怕精度跪建议用long double或者extended

样例输入

3
0 1
1 2

样例输出

5.6667


题解

期望+树的点分治+FFT

由于期望可加,因此所求等于 $\sum\limits_{i=1}^n\sum\limits_{j=1}^nP(j在i的点分树子树内)$ 。

而 $j$ 在 $i$ 的点分树子树内,又相当于:$i$ 到 $j$ 的路径上的所有点中(包括 $i$ 和 $j$),$i$ 是第一个选择的。因为如果其它点先被选择则会将 $i$ 与 $j$ 分开,使得 $j$ 不在 $i$ 的点分树内。

这些点中,显然每个点作为第一个选择的点的概率都是相等的,因此概率为 $\frac 1{dis(i,j)}$ ( $dis(i,i)=1$ )。

所求转化为求 $\sum\limits_{i=1}^n\sum\limits_{j=1}^ndis(i,j)$ ,即求距离等于每个值的点对数目。

考虑点分治,每次统计经过根节点路径的答案。dfs一遍子树得出距离等于每个值的点的个数,用容斥(任选两个 - 在同一棵子树内选两个)的方法得出答案。

容易发现求答案的过程实际上就是自身与自身求卷积,因此使用FFT快速求解。

由于距离范围(多项式次数)不会超过子树大小,因此时间复杂度为 $T(n)=O(n\log n)+2(T(\frac n2)+O(\frac n2\log n))=O(n\log^2n)$

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 30010
using namespace std;
const double pi = acos(-1);
struct data
{
double x , y;
data() {}
data(double a , double b) {x = a , y = b;}
data operator+(const data &a)const {return data(x + a.x , y + a.y);}
data operator-(const data &a)const {return data(x - a.x , y - a.y);}
data operator*(const data &a)const {return data(x * a.x - y * a.y , x * a.y + y * a.x);}
}A[65550];
int head[N] , to[N << 1] , next[N << 1] , cnt , vis[N] , si[N] , ms[N] , sum , root , deep[N] , val[N] , tot , num[N];
inline void add(int x , int y)
{
to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
void getroot(int x , int fa)
{
int i;
si[x] = 1 , ms[x] = 0;
for(i = head[x] ; i ; i = next[i])
if(!vis[to[i]] && to[i] != fa)
getroot(to[i] , x) , si[x] += si[to[i]] , ms[x] = max(ms[x] , si[to[i]]);
ms[x] = max(ms[x] , sum - si[x]);
if(ms[x] < ms[root]) root = x;
}
void getdeep(int x , int fa)
{
int i;
val[++tot] = deep[x];
for(i = head[x] ; i ; i = next[i])
if(!vis[to[i]] && to[i] != fa)
deep[to[i]] = deep[x] + 1 , getdeep(to[i] , x);
}
void fft(data *a , int n , int flag)
{
int i , j , k;
for(i = k = 0 ; i < n ; i ++ )
{
if(i > k) swap(a[i] , a[k]);
for(j = n >> 1 ; (k ^= j) < j ; j >>= 1);
}
for(k = 2 ; k <= n ; k <<= 1)
{
data wn(cos(2 * pi * flag / k) , sin(2 * pi * flag / k));
for(i = 0 ; i < n ; i += k)
{
data w(1 , 0) , t;
for(j = i ; j < i + (k >> 1) ; j ++ , w = w * wn)
t = w * a[j + (k >> 1)] , a[j + (k >> 1)] = a[j] - t , a[j] = a[j] + t;
}
}
if(flag == -1)
for(i = 0 ; i < n ; i ++ )
a[i].x /= n;
}
void calc(int flag)
{
int i , mx = 0 , n = 1;
for(i = 1 ; i <= tot ; i ++ ) mx = max(mx , val[i]);
while(n <= 2 * mx) n <<= 1;
for(i = 0 ; i < n ; i ++ ) A[i].x = A[i].y = 0;
for(i = 1 ; i <= tot ; i ++ ) A[val[i]].x ++ ;
fft(A , n , 1);
for(i = 0 ; i < n ; i ++ ) A[i] = A[i] * A[i];
fft(A , n , -1);
for(i = 0 ; i <= 2 * mx ; i ++ ) num[i] += flag * (int)(A[i].x + 0.1);
}
void dfs(int x)
{
int i;
vis[x] = 1 , deep[x] = tot = 0 , getdeep(x , 0) , calc(1);
for(i = head[x] ; i ; i = next[i])
{
if(!vis[to[i]])
{
deep[to[i]] = 1 , tot = 0 , getdeep(to[i] , 0) , calc(-1);
sum = si[to[i]] , root = 0 , getroot(to[i] , 0) , dfs(root);
}
}
}
int main()
{
int n , i , x , y;
long double ans = 0;
scanf("%d" , &n);
for(i = 1 ; i < n ; i ++ ) scanf("%d%d" , &x , &y) , add(x + 1 , y + 1) , add(y + 1 , x + 1);
sum = ms[0] = n , root = 0 , getroot(1 , 0) , dfs(root);
for(i = 0 ; i < n ; i ++ ) ans += (long double)num[i] / (i + 1);
printf("%.4Lf\n" , ans);
return 0;
}

【bzoj3451】Tyvj1953 Normal 期望+树的点分治+FFT的更多相关文章

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

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

  2. BZOJ3451: Tyvj1953 Normal

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

  3. BZOJ3451 Tyvj1953 Normal 【期望 + 点分治 + NTT】

    题目链接 BZOJ3451 题解 考虑每个点产生的贡献,即为该点在点分树中的深度期望值 由于期望的线性,最后的答案就是每个点贡献之和 对于点对\((i,j)\),考虑\(j\)成为\(i\)祖先的概率 ...

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

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

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

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

  6. bzoj 3451: Tyvj1953 Normal [fft 点分治 期望]

    3451: Tyvj1953 Normal 题意: N 个点的树,点分治时等概率地随机选点,代价为当前连通块的顶点数量,求代价的期望值 百年难遇的点分治一遍AC!!! 今天又去翻了一下<具体数学 ...

  7. 【BZOJ3451】Tyvj1953 Normal - 点分治+FFT

    题目来源:NOI2019模拟测试赛(七) 非原题面,题意有略微区别 题意: 吐槽: 心态崩了. 好不容易场上想出一题正解,写了三个小时结果写了个假的点分治,卡成$O(n^2)$ 我退役吧. 题解: 原 ...

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

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

  9. 【BZOJ3451】Normal (点分治)

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

随机推荐

  1. P2889 [USACO07NOV]挤奶的时间Milking Time

    P2889 [USACO07NOV]挤奶的时间Milking Time 奶牛Bessie在0~N时间段产奶.农夫约翰有M个时间段可以挤奶,时间段f,t内Bessie能挤到的牛奶量e.奶牛产奶后需要休息 ...

  2. Hadoop生态圈-Flume的组件之自定义Sink

    Hadoop生态圈-Flume的组件之自定义Sink 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客主要介绍sink相关的API使用两个小案例,想要了解更多关于API的小技 ...

  3. Spark记录-Scala字符串

    Scala字符串 在Scala中的字符串和Java中的一样,字符串是一个不可变的对象,也就是一个不能修改的对象.可以修改的对象,如数组,称为可变对象.字符串是非常有用的对象,在本节的最后部分,我们将介 ...

  4. 卸载并安装指定版本Angular CLI

    1.卸载之前的版本 npm uninstall -g @angular/cli 2.清除缓存,确保卸载干净 npm cache clean 3.检查是否卸载干净 输入命令 ng -v 若显示comma ...

  5. 那些年的 网络通信之 TCP/IP 传输控制协议 ip 加 端口 ---

    /* 一个文本小写转换为大写的小程序,当客户端从键盘录入一串字符串发送到服务端服务端转换为大写返回给客户端 */ import java.io.*; import java.net.*; class ...

  6. 用matplotlib制作的比较满意的蜡烛图

    用matplotlib制作的比较满意的蜡烛图 2D图形制作包, 功能强大, 习练了很久, 终于搞定了一个比较满意的脚本. 特点: 使用方面要非常简单 绘制出来的图要非常的满意, 具有如下的特点 时间和 ...

  7. 【原创】javascript模板引擎的简单实现

    本来想把之前对artTemplate源码解析的注释放上来分享下,不过隔了一年,找不到了,只好把当时分析模板引擎原理后,自己尝试 写下的模板引擎与大家分享下,留个纪念,记得当时还对比了好几个模板引擎来着 ...

  8. AngularJs -- 模 块

    在JavaScript中,将函数代码全部定义在全局命名空间中绝对不是什么好主意,这样做会导致冲突从而是调试变得非常困难,浪费宝贵的时间. 上一章介绍数据绑定时,就是写在全局命名空间中定义的函数. 在A ...

  9. iOS 提交应用过程出现的错误及#解决方案#images can't contain alpha channels or transparencies

        本文永久地址为http://www.cnblogs.com/ChenYilong/p/3977542.html ,转载请注明出处.    当你试图通过<预览>"导出&qu ...

  10. python的__get__、__set__、__delete__(1)

    内容:    描述符引导        摘要        定义和介绍        描述符协议        调用描述符        样例        Properties        函数和 ...