题目描述:
见洛谷
n
≤
2
∗
1
0
5
n\le2*10^5
n≤2∗105
题目分析:
首先考虑怎么解决
φ
(
i
∗
j
)
\varphi(i*j)
φ(i∗j)。
我们希望的自然是把它变成
φ
(
i
)
∗
φ
(
j
)
\varphi(i)*\varphi(j)
φ(i)∗φ(j) 方便独立计算,那么观察这两个形式的差别:
φ
(
i
)
∗
φ
(
j
)
=
i
∗
j
∗
∏
p
∣
i
(
1
−
1
p
)
∏
p
∣
j
(
1
−
1
p
)
φ
(
i
∗
j
)
=
i
∗
j
∗
∏
p
∣
i
j
(
1
−
1
p
)
\begin{aligned}\varphi(i)*\varphi(j)&=i*j*\prod_{p|i}(1-\frac 1p)\prod_{p|j}(1-\frac 1p)\\\varphi(i*j)&=i*j*\prod_{p|ij}(1-\frac 1p)\end{aligned}
φ(i)∗φ(j)φ(i∗j)=i∗j∗p∣i∏(1−p1)p∣j∏(1−p1)=i∗j∗p∣ij∏(1−p1)容易发现
φ
(
i
)
∗
φ
(
j
)
\varphi(i)*\varphi(j)
φ(i)∗φ(j) 多乘的是
g
c
d
(
i
,
j
)
gcd(i,j)
gcd(i,j) 的质因子在
φ
\varphi
φ中的形式,我们把它写成
φ
(
g
c
d
(
i
,
j
)
)
g
c
d
(
i
,
j
)
\varphi(gcd(i,j))\over gcd(i,j)
gcd(i,j)φ(gcd(i,j))
于是
φ
(
i
∗
j
)
=
φ
(
i
)
φ
(
j
)
g
c
d
(
i
,
j
)
φ
(
g
c
d
(
i
,
j
)
)
\varphi(i*j)={\varphi(i)\varphi(j)gcd(i,j)\over\varphi(gcd(i,j))}
φ(i∗j)=φ(gcd(i,j))φ(i)φ(j)gcd(i,j)
回到原题目中,我们枚举
g
c
d
(
a
i
,
a
j
)
=
d
gcd(a_i,a_j)=d
gcd(ai,aj)=d,那么原式(去掉前面的
1
n
(
n
−
1
)
\frac 1{n(n-1)}
n(n−1)1)等于
∑
d
=
1
n
d
φ
(
d
)
∑
i
=
1
n
∑
j
=
1
n
φ
(
a
i
)
φ
(
a
j
)
[
g
c
d
(
a
i
,
a
j
)
=
=
d
]
d
i
s
t
(
a
i
,
a
j
)
\sum_{d=1}^n{d\over \varphi(d)}\sum_{i=1}^n\sum_{j=1}^n\varphi(a_i)\varphi(a_j)[gcd(a_i,a_j)==d]dist(a_i,a_j)
d=1∑nφ(d)di=1∑nj=1∑nφ(ai)φ(aj)[gcd(ai,aj)==d]dist(ai,aj)
记 f ( d ) = ∑ i = 1 n ∑ j = 1 n φ ( a i ) φ ( a j ) [ g c d ( a i , a j ) = = d ] d i s t ( a i , a j ) f(d)=\sum_{i=1}^n\sum_{j=1}^n\varphi(a_i)\varphi(a_j)[gcd(a_i,a_j)==d]dist(a_i,a_j) f(d)=∑i=1n∑j=1nφ(ai)φ(aj)[gcd(ai,aj)==d]dist(ai,aj)。
这个
[
g
c
d
(
a
i
,
a
j
)
=
=
d
]
[gcd(a_i,a_j)==d]
[gcd(ai,aj)==d]的限制可以利用莫比乌斯反演转化成计算所有
g
c
d
gcd
gcd等于
d
d
d的倍数的点对。
即计算
F
(
d
)
=
∑
d
∣
x
f
(
x
)
F(d)=\sum_{d|x}f(x)
F(d)=∑d∣xf(x)。而
F
(
d
)
=
∑
d
∣
a
i
∑
d
∣
a
j
φ
(
a
i
)
φ
(
a
j
)
d
i
s
t
(
a
i
,
a
j
)
F(d)=\sum_{d|a_i}\sum_{d|a_j}\varphi(a_i)\varphi(a_j)dist(a_i,a_j)
F(d)=d∣ai∑d∣aj∑φ(ai)φ(aj)dist(ai,aj)这个可以将
d
i
s
t
(
a
i
,
a
j
)
dist(a_i,a_j)
dist(ai,aj)拆开后用虚树DP快速计算。因为
a
i
a_i
ai的权值是排列,所以总点数是
O
(
n
ln
n
)
O(n\ln n)
O(nlnn)的。
然后
f
(
d
)
=
∑
d
∣
x
F
(
x
)
∗
μ
(
x
d
)
f(d)=\sum_{d|x}F(x)*\mu(\frac xd)
f(d)=∑d∣xF(x)∗μ(dx)。
最后再乘上
1
n
(
n
−
1
)
\frac 1{n(n-1)}
n(n−1)1就可以了。总复杂度
O
(
n
ln
n
)
O(n\ln n)
O(nlnn)。
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);
}