传送门
题解:
前面那个关于 n n n的式子丢掉不管。
首先我们可以魔改树的标号使得我们需要求的式子变成下面这个:
A n s = ∑ i = 1 n ∑ j = 1 n ϕ ( i j ) d i s t ( i , j ) Ans=\sum_{i=1}^n\sum_{j=1}^n\phi(ij)dist(i,j) Ans=i=1∑nj=1∑nϕ(ij)dist(i,j)
对于欧拉函数,有: ϕ ( i j ) = ϕ ( i ) ϕ ( j ) g c d ( i , j ) ϕ ( g c d ( i , j ) ) \phi(ij)=\frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i,j))} ϕ(ij)=ϕ(gcd(i,j))ϕ(i)ϕ(j)gcd(i,j)
则莫比乌斯反演结果为:
A n s = ∑ T = 1 n ∑ d ∣ T d μ ( T d ) ϕ ( d ) ∑ i = 1 ⌊ n T ⌋ ∑ j = 1 ⌊ n T ⌋ ϕ ( i T ) ϕ ( j T ) d i s t ( i T , j T ) Ans=\sum_{T=1}^n\sum_{d\mid T}\frac{d\mu(\frac{T}{d})}{\phi(d)}\sum_{i=1}^{\lfloor\frac{n}{T}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{T}\rfloor}\phi(iT)\phi(jT)dist(iT,jT) Ans=T=1∑nd∣T∑ϕ(d)dμ(dT)i=1∑⌊Tn⌋j=1∑⌊Tn⌋ϕ(iT)ϕ(jT)dist(iT,jT)
令 g ( n ) = ∑ d ∣ n d μ ( n d ) ϕ ( d ) g(n)=\sum_{d\mid n}\frac{d\mu(\frac{n}{d})}{\phi(d)} g(n)=∑d∣nϕ(d)dμ(dn),则 g g g可以在 O ( n log n ) O(n\log n) O(nlogn)时间内处理完毕。
枚举所有的 T T T,则还剩下一个问题:如何求 ∑ i = 1 ⌊ n T ⌋ ∑ j = 1 ⌊ n T ⌋ ϕ ( i T ) ϕ ( j T ) d i s t ( i T , j T ) \sum_{i=1}^{\lfloor\frac{n}{T}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{T}\rfloor}\phi(iT)\phi(jT)dist(iT,jT) ∑i=1⌊Tn⌋∑j=1⌊Tn⌋ϕ(iT)ϕ(jT)dist(iT,jT)
实际上建完虚树后就是求 ∑ i ∑ j v a l i v a l j d i s t ( i , j ) \sum_{i}\sum_{j}val_ival_jdist(i,j) ∑i∑jvalivaljdist(i,j)
这个东西随便搞一个 O ( n ) O(n) O(n)的树形DP就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;
while(!isdigit(c=gc()));T num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int getint(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline int power(int a,int b,int res=1){
for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));
return res;
}
inline void Inc(int &a,int b){(a+=b)>=mod&&(a-=mod);}
inline void Dec(int &a,int b){(a-=b)<0&&(a+=mod);}
cs int P=2e5+5;
int phi[P],mu[P],inv[P],g[P];
int prime[P],pcnt;
bool mark[P];
inline void linear_sieves(int len){
phi[1]=mu[1]=inv[1]=inv[0]=1;
for(int re i=2;i<=len;++i){
inv[i]=mul(inv[mod%i],mod-mod/i);
if(!mark[i])prime[++pcnt]=i,phi[i]=i-1,mu[i]=mod-1;
for(int re j=1;i*prime[j]<=len;++j){
mark[i*prime[j]]=true;
if(i%prime[j]){
phi[i*prime[j]]=phi[i]*(prime[j]-1);
Dec(mu[i*prime[j]],mu[i]);
}
else {
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
}
}
for(int i=1;i<=len;++i){
for(int re j=i,k=1,t=mul(i,inv[phi[i]]);j<=len;j+=i,++k)
Inc(g[j],mul(t,mu[k]));
}
}
cs int N=2e5+5;
int n;
std::vector<int> G[N];
inline void addedge(int u,int v){
G[u].push_back(v);
G[v].push_back(u);
}
namespace ST{
int st[20][N<<1],dep[N],clk;
int Log[N<<1],in[N],out[N];
void dfs(int u,int pa){
dep[u]=dep[pa]+1;
st[0][in[u]=++clk]=u;
for(int re v:G[u])if(v!=pa){
dfs(v,u);
st[0][++clk]=u;
}out[u]=clk;
}
inline void init(){
dfs(1,0);Log[0]=-1;
for(int re i=1;i<=clk;++i)Log[i]=Log[i>>1]+1;
for(int re i=1;(1<<i)<=clk;++i)
for(int re j=1;j+(1<<i)-1<=clk;++j)
st[i][j]=dep[st[i-1][j]]<dep[st[i-1][j+(1<<i-1)]]?st[i-1][j]:st[i-1][j+(1<<i-1)];
}
inline int LCA(int u,int v){
int l=in[u],r=in[v];
if(l>r)std::swap(l,r);
int t=Log[r-l+1];
return dep[st[t][l]]<dep[st[t][r-(1<<t)+1]]?st[t][l]:st[t][r-(1<<t)+1];
}
inline int dist(int u,int v){return dep[u]+dep[v]-(dep[LCA(u,v)]<<1);}
}
using ST::LCA;
using ST::dist;
using ST::in;
using ST::out;
using ST::dep;
int id[N],cnt;
int val[N];
namespace VT{
struct edge{
int to,w;
edge(int _to,int _w):to(_to),w(_w){}
};
std::vector<edge> G[N];
int st[N],top;
inline void ins(int u){
if(!top){st[++top]=u;return ;}
int v=LCA(u,st[top]);
while(top&&dep[st[top-1]]>dep[v]){
G[st[top-1]].push_back(edge(st[top],dist(st[top-1],st[top])));
--top;
}
if(dep[v]<dep[st[top]]){
G[v].push_back(edge(st[top],dist(v,st[top])));
--top;
}
if(!top||dep[st[top]]<dep[v])st[++top]=v;
st[++top]=u;
}
int path[N],ans[N],sum[N];
void dp(int u,int pa){
path[u]=ans[u]=0;sum[u]=val[u];val[u]=0;
for(auto &e:G[u]){
int v=e.to;
dp(v,u);
Inc(ans[u],ans[v]);
Inc(ans[u],mul(sum[v],path[u]));
Inc(ans[u],mul(sum[u],path[v]));
Inc(ans[u],mul(e.w,mul(sum[u],sum[v])));
Inc(sum[u],sum[v]);
Inc(path[u],path[v]);
Inc(path[u],mul(sum[v],e.w));
}
G[u].clear();
}
inline int solve(){
std::sort(id+1,id+cnt+1,[](int u,int v){return in[u]<in[v];});
top=0;if(id[1]!=1)st[top=1]=1;
for(int re i=1;i<=cnt;++i)ins(id[i]);
while(top>1){
int u=st[top],v=st[--top];
G[v].push_back(edge(u,dist(u,v)));
}
dp(1,0);
return ans[1];
}
}
signed main(){
// freopen("surprise.in","r",stdin);
n=getint();linear_sieves(n);
for(int re i=1;i<=n;++i)id[i]=getint();
for(int re i=1;i<n;++i)addedge(id[getint()],id[getint()]);
ST::init();
int ans=0;
for(int re i=1,lim=n>>1;i<=lim;++i){
cnt=0;
for(int re j=i;j<=n;j+=i)
id[++cnt]=j,val[j]=phi[j];
Inc(ans,mul(g[i],VT::solve()));
}
cout<<power(mul(n,n-1),mod-2,add(ans,ans))<<"\n";
return 0;
}