題目描述:
見洛谷
題目分析:
首先考慮怎麼解決 。
我們希望的自然是把它變成 方便獨立計算,那麼觀察這兩個形式的差別:
容易發現 多乘的是 的質因子在中的形式,我們把它寫成
於是
回到原題目中,我們枚舉,那麼原式(去掉前面的)等於
記。
這個的限制可以利用莫比烏斯反演轉化成計算所有等於的倍數的點對。
即計算。而 這個可以將拆開後用虛樹DP快速計算。因爲的權值是排列,所以總點數是的。
然後 。
最後再乘上就可以了。總複雜度。
Code:
#include<bits/stdc++.h>
#define maxn 200005
using namespace std;
const int mod = 1e9+7;
int n,a[maxn],pos[maxn],q[maxn],sz,mu[maxn],phi[maxn],ans,F[maxn];
int Pow(int a,int b){int s=1;for(;b;b>>=1,a=1ll*a*a%mod) b&1&&(s=1ll*s*a%mod); return s;}
void Pre(const int N){
phi[1]=mu[1]=1; static int p[maxn],cnt=0; static bool v[maxn];
for(int i=2;i<=N;i++){
if(!v[i]) p[++cnt]=i,phi[i]=i-1,mu[i]=-1;
for(int j=1,k;j<=cnt&&(k=i*p[j])<=N;j++){
v[k]=1; if(i%p[j]==0) {phi[k]=phi[i]*p[j];break;}
phi[k]=phi[i]*(p[j]-1),mu[k]=-mu[i];
}
}
}
const int Log = 18;
int dfn[maxn],st[19][maxn*2],lg[maxn*2],dep[maxn],idx;
int fir[maxn],nxt[maxn<<1],to[maxn<<1],tot;
void line(int x,int y){nxt[++tot]=fir[x],fir[x]=tot,to[tot]=y;}
void dfs(int u,int ff){
dep[u]=dep[ff]+1,st[0][++idx]=u,dfn[u]=idx;
for(int i=fir[u],v;i;i=nxt[i]) if((v=to[i])!=ff)
dfs(v,u),st[0][++idx]=u;
}
int LCA(int x,int y){
if((x=dfn[x])>(y=dfn[y])) swap(x,y);
int k=lg[y-x+1];
return dep[st[k][x]]<dep[st[k][y-(1<<k)+1]]?st[k][x]:st[k][y-(1<<k)+1];
}
namespace VTree{
int ret,k,sum[maxn],S[maxn],tp;
bool kp[maxn];
bool cmp(int i,int j){return dfn[i]<dfn[j];}
void dfs2(int u){
if(kp[u]) sum[u]=phi[a[u]],ret=(ret+1ll*phi[a[u]]*phi[a[u]]*dep[u])%mod;
for(int i=fir[u],v;i;i=nxt[i])
dfs2(v=to[i]),ret=(ret+2ll*sum[u]*sum[v]%mod*dep[u])%mod,sum[u]=(sum[u]+sum[v])%mod;
}
int solve(){
sort(q+1,q+1+sz,cmp),k=sz,ret=0;
for(int i=1;i<=k;i++) kp[q[i]]=1;
for(int i=(S[tp=1]=q[1],2);i<=k;i++){
int lca=LCA(S[tp],q[i]);
for(;dfn[lca]<=dfn[S[tp-1]];tp--) line(S[tp-1],S[tp]);
if(lca!=S[tp]) line(lca,S[tp]),S[tp]=q[++sz]=lca;
S[++tp]=q[i];
}
for(;tp>1;tp--) line(S[tp-1],S[tp]);
dfs2(S[1]),ret=-ret;
for(int i=1;i<=k;i++) ret=(ret+1ll*phi[a[q[i]]]*dep[q[i]]%mod*sum[S[1]])%mod;
for(tot=0;sz;sz--) fir[q[sz]]=sum[q[sz]]=kp[q[sz]]=0;
return ret*2%mod;
}
}
int main()
{
scanf("%d",&n);
Pre(n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),pos[a[i]]=i;
for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),line(x,y),line(y,x);
dfs(1,0),lg[0]=-1;
for(int i=1;i<=idx;i++) lg[i]=lg[i>>1]+1;
for(int j=1;j<=Log;j++) for(int i=1,l=1<<j;i+l-1<=idx;i++)
st[j][i]=dep[st[j-1][i]]<dep[st[j-1][i+(l>>1)]]?st[j-1][i]:st[j-1][i+(l>>1)];
memset(fir,0,sizeof fir),tot=0;
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j+=i) q[++sz]=pos[j];
F[i]=VTree::solve();
}
for(int i=1;i<=n;i++){
int now=0;
for(int j=i;j<=n;j+=i) now=(now+F[j]*mu[j/i])%mod;
ans=(ans+1ll*i*Pow(phi[i],mod-2)%mod*now)%mod;
}
printf("%d\n",((1ll*ans*Pow(1ll*n*(n-1)%mod,mod-2))%mod+mod)%mod);
}