根据期望的线性性,我们算出每个点期望被计算次数,然后进行累加.

考虑点 $x$ 对点 $y$ 产生了贡献,那么说明 $(x,y)$ 之间的点中 $x$ 是第一个被删除的.

这个期望就是 $\frac{1}{dis(x,y)+1}$,所以我们只需求 $\sum_{i=1}^{n}\sum_{j=1}^{n}\frac{1}{dis(i,j)+1}$ 即可.

然后这个直接求是求不出来的,所以需要用点分治+FFT来算树上每种距离都出现了多少次.

code:

#include <bits/stdc++.h>
using namespace std;
#define N 500003
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
const double pi=acos(-1);
ll ans[N];
int edges,root,sn,n,mxdep;
int size[N],mx[N],hd[N],to[N<<1],nex[N<<1],vis[N];
inline void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
struct cpx
{
double x,y;
cpx(double a=0,double b=0) { x=a,y=b; }
cpx operator+(const cpx b) { return cpx(x+b.x,y+b.y); }
cpx operator-(const cpx b) { return cpx(x-b.x,y-b.y); }
cpx operator*(const cpx b) { return cpx(x*b.x-y*b.y,x*b.y+y*b.x); }
}A[N],B[N];
void fft(cpx *a,int len,int flag)
{
int i,j,k,mid;
for(i=k=0;i<len;++i)
{
if(i>k) swap(a[i],a[k]);
for(j=len>>1;(k^=j)<j;j>>=1);
}
for(mid=1;mid<len;mid<<=1)
{
cpx wn(cos(pi/mid), flag*sin(pi/mid)),x,y;
for(i=0;i<len;i+=mid<<1)
{
cpx w(1,0);
for(j=0;j<mid;++j)
{
x=a[i+j],y=w*a[i+j+mid];
a[i+j]=x+y;
a[i+j+mid]=x-y;
w=w*wn;
}
}
}
if(flag==-1) for(int i=0;i<len;++i) a[i].x/=(double)len;
}
void getroot(int u,int ff)
{
size[u]=1,mx[u]=0;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff||vis[v]) continue;
getroot(v,u);
size[u]+=size[v];
mx[u]=max(mx[u], size[v]);
}
mx[u]=max(mx[u], sn-size[u]);
if(mx[u]<mx[root]) root=u;
}
void dfs(int u,int ff,int d)
{
++A[d].x;
mxdep=max(mxdep,d);
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(v==ff||vis[v]) continue;
dfs(v,u,d+1);
}
}
void calc(int u,int d)
{
mxdep=0;
dfs(u,0,d==1?0:1);
int len=1;
while(len<=(mxdep+mxdep+2)) len<<=1;
fft(A,len,1);
for(int i=0;i<len;++i) A[i]=A[i]*A[i];
fft(A,len,-1);
for(int i=0;i<min(len,n);++i) ans[i]+=(ll)(A[i].x+0.1)*d;
for(int i=0;i<len;++i) A[i].x=A[i].y=0;
}
void solve(int u)
{
vis[u]=1;
calc(u,1);
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(vis[v]) continue;
calc(v,-1);
}
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(vis[v]) continue;
root=0,sn=size[v],getroot(v,u);
solve(root);
}
}
int main()
{
// setIO("input");
int i,j;
scanf("%d",&n);
for(i=1;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
++x,++y;
add(x,y),add(y,x);
}
mx[0]=sn=n;
getroot(1,0);
solve(root);
double tmp=0.0;
for(int i=0;i<n;++i)
{
tmp+=(double) ans[i]/(i+1);
}
printf("%.4f\n",tmp);
return 0;
}

  

BZOJ 3451: Tyvj1953 Normal 点分治+FFT的更多相关文章

  1. 3451: Tyvj1953 Normal 点分治 FFT

    国际惯例的题面:代价理解为重心和每个点这个点对的代价.根据期望的线性性,我们枚举每个点,计算会产生的ij点对的代价即可.那么,i到j的链上,i必须是第一个被选择的点.对于i来说,就是1/dis(i,j ...

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

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

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

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

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

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

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

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

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

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

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

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

  8. BZOJ 4555: [Tjoi2016&Heoi2016]求和 [分治FFT 组合计数 | 多项式求逆]

    4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...

  9. bzoj 4836 [Lydsy1704月赛]二元运算 分治FFT+生成函数

    [Lydsy1704月赛]二元运算 Time Limit: 8 Sec  Memory Limit: 128 MBSubmit: 577  Solved: 201[Submit][Status][Di ...

随机推荐

  1. Redis cluster的核心原理分析

    一.节点间的内部通信机制 1.基础通信原理 (1)redis cluster节点间采取gossip协议进行通信 跟集中式不同,不是将集群元数据(节点信息,故障,等等)集中存储在某个节点上,而是互相之间 ...

  2. C# vb .net实现负片特效滤镜

    在.net中,如何简单快捷地实现Photoshop滤镜组中的负片特效呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一步 ...

  3. vim打开多个文件、同时显示多个文件、在文件之间切换

    打开多个文件: 1.vim还没有启动的时候: 在终端里输入  vim file1 file2 ... filen便可以打开所有想要打开的文件 2.vim已经启动 输入 :open file 可以再打开 ...

  4. 如何在linux中重置Mysql访问密码

    目录 跳过密码认证 重启MySQL: 用sql来修改root的密码 去掉'跳过密码'代码 假设我们使用的是root账户. 跳过密码认证 重置密码的第一步就是跳过MySQL的密码认证过程,方法如下: # ...

  5. SqlDataSource控件超时的困惑

      想用最简单的SqlDataSource控件完成对一个记录数很多的表的查询操作,结果出现超时异常,找了些解决方法都不奏效,后来在www.codeproject.com查到高手也放弃了用控件的方法,于 ...

  6. Android App 架构演变

    文:https://www.jianshu.com/p/ce26e7960926 最近App项目(MVC架构)越做越大,协同开发效率较低,维护困难,所以产生了调整架构的想法,在 简书.csdn.知乎上 ...

  7. Java使用JsonPatch

    老规矩,概念的东西不再此处体现,baidu即可自行解决,直入主题,动手第一. 导入所需的jar文件 pom.xml     <dependencies>        <depend ...

  8. 什么影响了mysql的性能-存储引擎层

    5.6版本以前默认是MyISam存储引擎,5.6版本之后默认支持的Innodb存储引擎,这两种也是最常用的. 存储引擎层 MyISAM 5.5之前版本默认存储引擎 存储引擎表由MYD和MYI组成 特性 ...

  9. VS Code好用到飞起的配置设置

    Visual Studio Code是一个轻量级但功能强大的源代码编辑器,可在桌面上运行,适用于Windows,macOS和Linux.它内置了对JavaScript,TypeScript和Node. ...

  10. Python入门篇-匿名函数

    Python入门篇-匿名函数 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.匿名函数概述 1>.什么是匿名函数 匿名,即没有名字 匿名函数,即没有名字的函数 2>. ...