tyvj1953 Normal
2018-03-08 13:56
435 查看
题目链接
正解:点分治+$FFT$。
很想吐槽一下$bzoj$,为什么搬了别的$oj$的题还设成权限题。。
首先我们考虑期望的线性性,即考虑每个点的贡献。
显然每个点的贡献就是它在点分树上的深度,所以我们进一步考虑哪些点在它到根的路径上。
我们考虑每一条路径的贡献,显然对于一条路径$(x,y)$,当且仅当$x$是路径上最浅的点时会对$y$有$1$的贡献。
那么这条路径$x$深度最浅的概率,实际上就是$\frac{1}{len(x,y)}$,因为每个点作为深度最浅的点的概率相等。
所以我们统计每一种长度的路径个数就行了,这个用$FFT$即可解决。
正解:点分治+$FFT$。
很想吐槽一下$bzoj$,为什么搬了别的$oj$的题还设成权限题。。
首先我们考虑期望的线性性,即考虑每个点的贡献。
显然每个点的贡献就是它在点分树上的深度,所以我们进一步考虑哪些点在它到根的路径上。
我们考虑每一条路径的贡献,显然对于一条路径$(x,y)$,当且仅当$x$是路径上最浅的点时会对$y$有$1$的贡献。
那么这条路径$x$深度最浅的概率,实际上就是$\frac{1}{len(x,y)}$,因为每个点作为深度最浅的点的概率相等。
所以我们统计每一种长度的路径个数就行了,这个用$FFT$即可解决。
#include <bits/stdc++.h> #define il inline #define RG register #define ll long long #define N (1000005) using namespace std; struct edge{ int nt,to; }g ; struct C{ double x,y; il C operator + (const C &a) const{ return (C){x+a.x,y+a.y}; } il C operator - (const C &a) const{ return (C){x-a.x,y-a.y}; } il C operator * (const C &a) const{ return (C){x*a.x-y*a.y,x*a.y+y*a.x}; } }a ; const double pi=acos(-1.0); int head ,vis ,dis ,son ,sz ,rev ,n,num,len,Max; double ans ,Ans; il int gi(){ RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return q*x; } il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; } il void fft(C *a,RG int n,RG int f){ for (RG int i=0;i<n;++i) if (i<rev[i]) swap(a[i],a[rev[i]]); for (RG int i=1;i<n;i<<=1){ C wn=(C){cos(pi/i),sin(f*pi/i)}; for (RG int j=0;j<n;j+=i<<1){ C w=(C){1,0},x,y; for (RG int k=0;k<i;++k,w=w*wn){ x=a[j+k],y=w*a[j+k+i]; a[j+k]=x+y,a[j+k+i]=x-y; } } } if (f==-1) for (RG int i=0;i<len;++i) a[i].x/=n; return; } il void getrt(RG int x,RG int p,RG int &rt){ son[x]=0,sz[x]=1; for (RG int i=head[x],v;i;i=g[i].nt){ v=g[i].to; if (v==p || vis[v]) continue; getrt(v,x,rt),sz[x]+=sz[v],son[x]=max(son[x],sz[v]); } son[x]=max(son[x],son[0]-sz[x]); if (son[rt]>=son[x]) rt=x; return; } il void getdis(RG int x,RG int p){ sz[x]=1,++a[dis[x]].x,Max=max(Max,dis[x]); for (RG int i=head[x],v;i;i=g[i].nt){ v=g[i].to; if (v==p || vis[v]) continue; dis[v]=dis[x]+1,getdis(v,x),sz[x]+=sz[v]; } return; } il void calc(RG int rt,RG int lim,RG int fg){ Max=0,dis[rt]=lim,getdis(rt,0); RG int lg=0; for (len=1;len<=(Max<<1);len<<=1) ++lg; for (RG int i=0;i<len;++i) rev[i]=rev[i>>1]>>1|((i&1)<<(lg-1)); fft(a,len,1); for (RG int i=0;i<len;++i) a[i]=a[i]*a[i]; fft(a,len,-1); for (RG int i=0;i<len;++i) ans[i]+=(ll)(a[i].x+0.5)*fg,a[i]=(C){0,0}; return; } il void solve(RG int x,RG int S){ RG int rt=0; son[0]=S,getrt(x,0,rt); vis[rt]=1,calc(rt,0,1); for (RG int i=head[rt];i;i=g[i].nt) if (!vis[g[i].to]) calc(g[i].to,1,-1); for (RG int i=head[rt];i;i=g[i].nt) if (!vis[g[i].to]) solve(g[i].to,sz[g[i].to]); return; } int main(){ #ifndef ONLINE_JUDGE freopen("normal.in","r",stdin); freopen("normal.out","w",stdout); #endif n=gi(); for (RG int i=1,u,v;i<n;++i) u=gi()+1,v=gi()+1,insert(u,v),insert(v,u); solve(1,n); for (RG int i=0;i<n;++i) Ans+=1.0*ans[i]/(i+1); printf("%0.4lf\n",Ans); return 0; }
相关文章推荐
- BZOJ3451: Tyvj1953 Normal
- [BZOJ3451][Tyvj1953]Normal
- Tyvj1953:Normal (点分治+FFT)
- 【bzoj3451】【Tyvj1953】Normal 题解
- bzoj 3451: Tyvj1953 Normal [fft 点分治 期望]
- 【BZOJ3451】Tyvj1953 Normal 点分治+FFT+期望
- bzoj 3451: Tyvj1953 Normal 点分治+fft
- [bzoj3451]Tyvj1953 Normal
- 【BZOJ 3451】Tyvj1953 Normal 思维题+期望概率+FFT+点分治
- BZOJ3451 Tyvj1953 Normal
- bzoj3451 Tyvj1953 Normal(期望概率+点分治+FFT)
- BZOJ3451 [Tyvj1953] Normal
- bzoj 3451: Tyvj1953 Normal
- BZOJ3451 Tyvj1953 Normal 【期望 + 点分治 + NTT】
- bzoj3451/Tyvj1953:Normal(点分治+FFT)
- [转]Compact Normal Storage for Small G-Buffers
- TYVJ 1014 乘法游戏
- ORA-00000 normal, successful completion处理
- php安装错误 (node.c:1953:error) 解决办法
- VersionToNormal.py