可以发现
3
个人间互不影响。
假设共有
用点分治求出有多少对幸运数就好了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x){
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
typedef long long ll;
const int N=50010;
int sz[N],f[N],Rt;
int a[11];
int k,n,m;
int t[N<<1],nx[N<<1],h[N],num;
ll Ans;
int x,y,sum;
int c[N],d[N],s[N],l,cnt;
bool b[N];
inline void Add(int x,int y){
t[++num]=y;nx[num]=h[x];h[x]=num;
}
void Get(int x,int y){
sz[x]=1;f[x]=0;
for(int i=h[x];i;i=nx[i]){
int v=t[i];
if(v==y||b[v])continue;
Get(v,x);
f[x]=max(f[x],sz[v]);
sz[x]+=sz[v];
}
f[x]=max(f[x],sum-sz[x]);
if(f[x]<f[Rt])Rt=x;
}
void Dfs(int x,int y,int z){
c[++l]=z;
for(int i=h[x];i;i=nx[i])
if(!b[t[i]]&&t[i]!=y)Dfs(t[i],x,z+1);
}
inline void Calc(int x,int y,int z){
l=cnt=0;
Dfs(x,0,y);
sort(c+1,c+l+1);
for(int i=1;i<=l;i){
int j=i;
for(;j<=l&&c[j]==c[i];j++);
d[++cnt]=c[i];s[cnt]=j-i;i=j;
}
for(int i=1;i<=m;i++){
int k=cnt;
for(int j=1;j<=k;j++){
for(;k>j&&d[k]+d[j]>a[i];k--);
if(d[k]+d[j]==a[i]){
if(j==k)Ans+=1ll*s[j]*(s[j]-1)/2*z;else
Ans+=1ll*s[k]*s[j]*z;
}
}
}
}
void Solve(int x){
Calc(x,0,1);
b[x]=1;
for(int i=h[x];i;i=nx[i]){
int v=t[i];
if(v==y||b[v])continue;
Calc(v,1,-1);
f[Rt=0]=sum=sz[v];Get(v,0);Solve(Rt);
}
}
inline void Work(int x){
double t=(double)x*(x-1)/2*Ans/n/(n-1)*2;
printf("%.2lf\n",t);
}
int main(){
Read(n);Read(m);
for(int i=1;i<=m;i++)Read(a[i]);
for(int i=1;i<n;i++)Read(x),Read(y),Add(x,y),Add(y,x);
f[Rt=0]=sum=n;Get(1,0);Solve(Rt);
Work((n+2)/3);Work((n+1)/3);Work(n/3);
return 0;
}