题解:
什么情况点i会对点j做贡献?在i~j路径上的点中,点j最先被选中,概率是1/[dis(i,j)+1]
答案=∑{1/[dis(i,j)+1]}
i,j
点分+FFT算出距离为1~n的点对数即可
AC code
什么情况点i会对点j做贡献?在i~j路径上的点中,点j最先被选中,概率是1/[dis(i,j)+1]
答案=∑{1/[dis(i,j)+1]}
i,j
点分+FFT算出距离为1~n的点对数即可
AC code
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
inline int rd(){int t;scanf("%d",&t);return t;}
#define F f[k&1]
#define G f[~k&1]
#define N 30010
#define md 998244353
ll w[N<<1],f[2][N<<1],cnt[N<<1];
ll pw(ll x,ll k){
ll t=1;
for (;k;k>>=1,x=x*x%md)
if (k&1) t=t*x%md;
return t;
}
void DFT(ll *a,int n,ll w0){
ll i,j,k;
for (i=w[0]=1;i<n;++i) w[i]=w[i-1]*w0%md;
for (k=i=0;i<n;++i) F[i]=a[i];
for (;i;++k) for (i=0;i<n>>1>>k;++i) for (j=0;j^1<<k;++j)
G[i<<k<<1|j]=(F[i<<k|j]+F[i<<k|j|n>>1]*w[j*n>>k>>1])%md,
G[i<<k<<1|j|1<<k]=(F[i<<k|j]-F[i<<k|j|n>>1]*w[j*n>>k>>1])%md;
for (i=0;i<n;++i) a[i]=G[i];
}
void NTT(ll *a,int n){
ll i,inv=pw(n,md-2);
DFT(a,n,pw(3,(md-1)/n));
for (i=0;i<n;i++) a[i]=a[i]*a[i]%md;
DFT(a,n,w[n-1]);
for (i=0;i<n;i++) a[i]=(a[i]*inv%md+md)%md;
}
#define V E[i].t
#define FOR for (int i=ft[u];i;i=E[i].n) if (!vis[V]&&V!=f)
struct edge{int t,n;}E[N<<1];
int SUM,R,D,n,i,x,y,tot;
int sum[N],ft[N],key[N],vis[N],ans[N<<1];
double ANS;
void up(int &x,int y){x=max(x,y);}
void Gsum(int u,int f){
sum[u]=1;
FOR Gsum(V,u),sum[u]+=sum[V];
}
void Groot(int u,int f){
key[u]=SUM-sum[u];
FOR Groot(V,u),up(key[u],sum[V]);
if (key[u]<key[R]) R=u;
}
void Gcnt(int u,int f,int d){
up(D,d);
++cnt[d];
FOR Gcnt(V,u,d+1);
}
void dev(int u,int k){
int i;
Gcnt(u,u,D=k==1?0:1);
for (++D;D-(D&-D);) D+=D&-D; D<<=1;
NTT(cnt,D);
for (i=0;i<=D;i++) ans[i]+=cnt[i]*k,cnt[i]=0;
}
void solve(int u){ int f=0;
dev(u,vis[u]=1);
FOR dev(V,-1);
FOR R=0,Gsum(V,V),SUM=sum[V],
Groot(V,V),solve(R);
}
int main(){
for (n=rd(),i=1;i<n;i++){
x=rd()+1,y=rd()+1;
E[++tot]=(edge){y,ft[x]},ft[x]=tot;
E[++tot]=(edge){x,ft[y]},ft[y]=tot;
}
key[0]=n;
solve(1);
for (i=1;i<=n;i++) ANS+=(double)ans[i-1]/i;
printf("%.4f",ANS);
return 0;
}