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

考虑点 $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. Cpp_Primer_4th_Edition-source-code

    Cpp_Primer_4th_Edition-source-code 根据书上的去找,官网已经找不到了,毕竟第6版都已经出来了.不过有的朋友用的还是第4版,我的纸质书是第5版,pdf是第4版,都有在看 ...

  2. Java的含义

    Java是一种广泛使用的计算机编程语言,拥有跨平台.面向对象.泛型编程的特性,广泛应用于企业级Web应用开发和移动应用开发. Java语言它不是软件,这里给各位初学者们详细解释一下.简单来说计算机语言 ...

  3. GO指南练习:切片

    最近开始GO语言的学习,在GO指南中练习到切片这个题目 练习:切片 实现 Pic.它应当返回一个长度为 dy 的切片,其中每个元素是一个长度为 dx,元素类型为 uint8 的切片.当你运行此程序时, ...

  4. setPos 详解

    etWindowPos 详解   函数名: SetWindowPos 头文件: winuser.h 函数原型: BOOL SetWindowPos ( HWND hWnd, //窗口句柄 HWND h ...

  5. jdbc 简单示例和优缺点

    一个使用JDBC的例子: Class.forName("com.mysql.cj.jdbc.Driver"); //加载驱动 Connection connection = Dri ...

  6. LOJ#2409. 「THUPC 2017」小 L 的计算题 / Sum(生成函数)

    题意 给定一个长为 \(n\) 的序列 \(\{a_i\}\) 对于 \(k \in [1, n]\) 求 \[ f_k = \sum_{i = 1}^{n} a_i^k \pmod {9982443 ...

  7. Java CookieUtils

    Java CookieUtils /** * <html> * <body> * <P> Copyright 1994 JsonInternational</ ...

  8. .net core获取数据库连接 抛出The type initializer to throw an exception

    原文:https://www.cnblogs.com/pudefu/p/7580722.html 在.NET Framework框架时代我们的应用配置内容一般都是写在Web.config或者App.c ...

  9. Linux RedHat7.0_64位系统中安装Oracle_11g_R2

    步骤一: 当然是安装rhel7操作系统啦(废话),建议在安装过程中系统软件类型选择最后一项[Server with GUI].其他的默认一般即可. 步骤二:在初装完成的系统中无法像Windows那样直 ...

  10. dump net core windbg 安装

    安装 1.下载工具windbg 地址:https://www.microsoft.com/zh-cn/p/windbg-preview/9pgjgd53tn86?SilentAuth=1&rt ...