题目大意
点分治过程中每次随机选择分治中心。
求期望复杂度。
期望的线性性
容易知道可以单独考虑每个点的贡献。
对于x和y,我们考虑y能否给x带来1的贡献,即y是否是x在点分树上的祖先。
那么Y必须是x到y上第一个被选择为分治中心的点。
一条路径上每个点成为第一个被选择的点概率均等,因此贡献为
1dis(i,j)
答案就是
∑ni=1∑nj=11dis(i,j)
这个怎么求???
我们需要知道每一种路径长度的条数。
那么可以点分治,然后FFT。
注意次数界限要和深度挂钩,否则复杂度不对。
同样要采取容斥的打法,即这一层不考虑计算非法,到下一层再去减。
这样就是两个log。
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef double db;
const db pi=acos(-1);
const int maxn=120000+10;
struct node{
db x,y;
friend node operator +(node a,node b){
node c;
c.x=a.x+b.x;c.y=a.y+b.y;
return c;
}
friend node operator -(node a,node b){
node c;
c.x=a.x-b.x;c.y=a.y-b.y;
return c;
}
friend node operator *(node a,node b){
node c;
c.x=a.x*b.x-a.y*b.y;c.y=a.x*b.y+a.y*b.x;
return c;
}
};
node d[maxn],c[maxn],e[maxn],f[maxn],tt[maxn];
int dep[maxn],size[maxn],a[maxn],cnt[maxn];
int h[maxn],go[maxn*2],next[maxn*2];
bool bz[maxn];
int i,j,k,l,t,n,m,tot,top,mx,len;
db ans,ce;
void add(int x,int y){
go[++tot]=y;
next[tot]=h[x];
h[x]=tot;
}
void travel(int x,int y){
a[++top]=x;
size[x]=1;
int t=h[x];
while (t){
if (!bz[go[t]]&&go[t]!=y){
travel(go[t],x);
size[x]+=size[go[t]];
}
t=next[t];
}
}
void dfs(int x,int y){
int t=h[x];
while (t){
if (!bz[go[t]]&&go[t]!=y){
dep[go[t]]=dep[x]+1;
dfs(go[t],x);
}
t=next[t];
}
}
void DFT(node *a,int sig){
int i;
fo(i,0,len-1){
int p=0;
for (int j=0,tp=i;j<ce;j++,tp/=2) p=(p<<1)+(tp%2);
tt[p]=a[i];
}
for (int m=2;m<=len;m*=2){
int half=m/2;
fo(i,0,half-1){
node wi;
wi.x=cos(i*pi*sig/half);wi.y=sin(i*pi*sig/half);
for (int j=i;j<len;j+=m){
node u=tt[j],v=tt[j+half]*wi;
tt[j]=u+v;
tt[j+half]=u-v;
}
}
}
if (sig==-1)
fo(i,0,len-1) tt[i].x/=len;
fo(i,0,len-1) a[i]=tt[i];
}
void FFT(node *a,node *b,node *c){
int i;
fo(i,0,len-1) e[i]=a[i],f[i]=b[i];
DFT(e,1);DFT(f,1);
fo(i,0,len-1) e[i]=e[i]*f[i];
DFT(e,-1);
fo(i,0,len-1) c[i]=e[i];
}
void calc(int f){
int i;
mx=0;
fo(i,1,top)
if (dep[a[i]]>mx) mx=dep[a[i]];
len=1;
while (len<=mx*2) len*=2;
ce=log(len)/log(2);
fo(i,0,len-1) d[i].x=0;
fo(i,1,top) d[dep[a[i]]].x++;
FFT(d,d,c);
fo(i,0,len-1) cnt[i]+=f*round(c[i].x);
}
void solve(int x,int y){
top=0;
travel(x,0);
if (y) calc(-1);
int i,j=x,k=0,t;
while (1){
t=h[j];
while (t){
if (!bz[go[t]]&&go[t]!=k&&size[go[t]]>top/2){
k=j;
j=go[t];
break;
}
t=next[t];
}
if (!t) break;
}
dep[j]=0;
dfs(j,0);
calc(1);
bz[j]=1;
t=h[j];
while (t){
if (!bz[go[t]]) solve(go[t],y+1);
t=next[t];
}
}
int main(){
//freopen("3451.in","r",stdin);
scanf("%d",&n);
fo(i,1,n-1){
scanf("%d%d",&j,&k);
j++;k++;
add(j,k);add(k,j);
}
solve(1,0);
fo(i,0,n-1) ans+=(db)1/(i+1)*cnt[i];
printf("%.4lf\n",ans);
}