练习套路的一道题。
首先 ϕ ( i j ) \phi(ij) ϕ(ij)怎么拆?这里要用到一个不怎么常见的套路, ϕ ( i j ) = ϕ ( i ) ϕ ( j ) gcd ( i , j ) ϕ ( gcd ( 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)。
让我们观察这个式子: ∑ d = 1 n d ϕ ( d ) ∑ i = 1 n ∑ j = 1 n ϕ ( i ) ϕ ( j ) [ gcd ( i , j ) = d ] dist(i,j) \sum_{d=1}^n\frac{d}{\phi(d)}\sum_{i=1}^n\sum_{j=1}^n\phi(i)\phi(j)[\gcd(i,j)=d]\text{dist(i,j)} ∑d=1nϕ(d)d∑i=1n∑j=1nϕ(i)ϕ(j)[gcd(i,j)=d]dist(i,j)
首先 ϕ ( i ) ϕ ( j ) \phi(i)\phi(j) ϕ(i)ϕ(j)可以看成两个点权之积,其次后面的艾佛森括号表示的是“恰好”的意思,那么我们可以想到将条件改写成 i , j i,j i,j均为 d d d的倍数。
考察: ∑ d ∣ i ∑ d ∣ j ϕ ( i ) ϕ ( j ) dist(i,j) \sum_{d|i}\sum_{d|j}\phi(i)\phi(j)\text{dist(i,j)} ∑d∣i∑d∣jϕ(i)ϕ(j)dist(i,j) 这个式子不就可以在虚树上统计答案吗?
那么我们只需容斥即可。记 g ( d ) = ∑ d ∣ i ∑ d ∣ j ϕ ( i ) ϕ ( j ) dist(i,j) g(d)=\sum_{d|i}\sum_{d|j}\phi(i)\phi(j)\text{dist(i,j)} g(d)=∑d∣i∑d∣jϕ(i)ϕ(j)dist(i,j), f ( d ) = ∑ i = 1 n ∑ j = 1 n ϕ ( i ) ϕ ( j ) [ gcd ( i , j ) = d ] dist(i,j) f(d)=\sum_{i=1}^n\sum_{j=1}^n\phi(i)\phi(j)[\gcd(i,j)=d]\text{dist(i,j)} f(d)=∑i=1n∑j=1nϕ(i)ϕ(j)[gcd(i,j)=d]dist(i,j)。那么 g ( d ) = ∑ d ∣ d ′ f ( d ′ ) g(d)=\sum_{d|d'}f(d') g(d)=∑d∣d′f(d′),显然可以得到 f ( d ) = ∑ d ∣ d ′ g ( d ′ ) μ ( d ′ d ) f(d)=\sum_{d|d'}g(d')\mu(\frac{d'}{d}) f(d)=∑d∣d′g(d′)μ(dd′),因此只需计算 g ( d ) g(d) g(d)。
只需把 d d d的倍数的点建虚树即可,这里不再赘述。
复杂度 O ( n log 2 n ) O(n\log^2 n) O(nlog2n)。
出题人是bot吧
#include<bits/stdc++.h>
#define pb push_back
#define ll long long
using namespace std;
const int mod=1e9+7;
const int N=200005;
int n,a[N],rk[N],dfn[N],son[N],fa[N],num,dep[N],siz[N],tp[N],dis[N];
ll f[N];
vector<int>g[N],g2[N];
ll fpow(ll x,ll y=mod-2){
ll z(1);
for(;y;y>>=1){
if(y&1)z=z*x%mod;
x=x*x%mod;
}return z;
}
int Lca(int x,int y){
int fx=tp[x],fy=tp[y];
while(fx!=fy){
if(dep[fx]>dep[fy])x=fa[fx];
else y=fa[fy];
fx=tp[x],fy=tp[y];
}return dep[x]<dep[y]?x:y;
}
void dfs(int u,int topf){
dfn[u]=++num,fa[u]=topf,siz[u]=1,dep[u]=dep[topf]+1;
for(auto v:g[u]){
if(v!=topf){
dfs(v,u),siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
}
void dfs2(int u,int topf){
tp[u]=topf;
if(son[u])dfs2(son[u],topf);
for(auto v:g[u]){
if(!tp[v]){
dfs2(v,v);
}
}
}
int prime[N],Cnt,mu[N],Vis[N],phi[N];
void init(int n){
mu[1]=phi[1]=1;
for(int i=2;i<=n;i++){
if(!Vis[i])prime[++Cnt]=i,mu[i]=-1,phi[i]=i-1;
for(int j=1;j<=Cnt&&prime[j]<=n/i;j++){
Vis[i*prime[j]]=1;
if(i%prime[j])mu[i*prime[j]]=-mu[i],phi[i*prime[j]]=phi[i]*(prime[j]-1);
else {
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
}
}
}
int p[N],vis[N],m,cnt,s[N];
vector<int>vec;
bool cmp(int x,int y){
return dfn[x]<dfn[y];
}
ll S,sum[N],res;
void dfs3(int u,int id){
sum[u]=0;if(vis[u])sum[u]=(sum[u]+phi[a[u]])%mod;
for(auto v:g2[u]){
dfs3(v,id);
f[id]=(f[id]+2*sum[v]*(S-sum[v])%mod*dis[v]%mod)%mod,sum[u]=(sum[u]+sum[v])%mod;
}
}
void add(int x,int y){
if(dfn[x]>dfn[y])swap(x,y);
g2[x].pb(y),dis[y]=dep[y]-dep[x];
}
int gcd(int x,int y){
return y==0?x:gcd(y,x%y);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n,init(n);for(int i=1;i<=n;i++)cin>>a[i],rk[a[i]]=i;
for(int i=1;i<n;i++){
int x,y;cin>>x>>y,g[x].pb(y),g[y].pb(x);
}dfs(1,0),dfs2(1,1);
for(int i=1;i<=n;i++){
m=S=0;
for(int j=i;j<=n;j+=i)p[++m]=rk[j],S=(S+phi[j])%mod,vis[rk[j]]=1,vec.pb(rk[j]);
s[cnt=1]=1,vec.pb(1);
sort(p+1,p+1+m,cmp);
for(int i=1;i<=m;i++){
if(p[i]==1)continue;
int u=p[i],v=Lca(u,s[cnt]);
if(s[cnt]==v)s[++cnt]=u;
else{
int lst=0;
while(dep[s[cnt]]>dep[v]){
if(lst)add(s[cnt],lst);
lst=s[cnt--];
}
if(s[cnt]==v){
add(s[cnt],lst),s[++cnt]=u;
}
else{
add(v,lst),s[++cnt]=v,vec.pb(v),s[++cnt]=u;
}
}
}for(int i=1;i<cnt;i++)add(s[i],s[i+1]);
dfs3(1,i);
for(int j=0;j<vec.size();j++)vis[vec[j]]=0,g2[vec[j]].clear();vec.clear();
}
for(int i=1;i<=n;i++){
ll tot=0;
for(int j=i;j<=n;j+=i){
tot=(tot+mu[j/i]*f[j]%mod)%mod;
}
res=(res+tot*i%mod*fpow(phi[i])%mod)%mod;
}
cout<<(res+mod)%mod*fpow(n)%mod*fpow(n-1)%mod;
}