含
n(≤10w)
个结点的树。边权为
1
,点权
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define rep(x,st,en) for(int x=st;x<=en;x++)
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int M=100005;
const int Num=100000;
typedef long long ll;
int nxt[M][18],bin[20];
int dep[M];
struct Edge{
int to,nxt;
}edge[M<<2];
//虚树中的边可以利用深度O(1)获得
int last[M];
int head[M];
int prv,allc;
int mul[M];
int id[M],n;
ll ans,val;
void ins(int u,int v){
edge[++allc]=(Edge){v,last[u]};
last[u]=allc;
}
void ins_(int u,int v){
edge[++allc]=(Edge){v,head[u]};
head[u]=allc;
}
bool cmp(int x,int y){
return id[x]<id[y];
}
int a[M+5];
int tot,top,dfs_clock;
int lca(int u,int v){
if(dep[u]<dep[v])swap(u,v);
int d=dep[u]-dep[v];
for(int i=0;i<18;i++)
if(bin[i]&d)
u=nxt[u][i];
if(u==v)return u;
for(int i=17;i>=0;i--)
if(nxt[u][i]!=nxt[v][i]){
u=nxt[u][i];
v=nxt[v][i];
}
return nxt[u][0];
}
int stk[M];
int sz[M];
void dfs1(int x,int f){
for(int i=last[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(y!=f){
dfs1(y,x);
sz[x]+=sz[y];
}
}
if(f)val+=1ll*abs(dep[x]-dep[f])*sz[x]*(tot-sz[x]);
}
void clear(int x,int f){
for(int i=last[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(y!=f)clear(y,x);
}
last[x]=sz[x]=0;
}
void solve(int K){
tot=top=0;
for(int i=K;i<=Num;i+=K)
for(int j=head[i];j;j=edge[j].nxt)
a[tot++]=edge[j].to;
if(tot<=1)return;
val=0;
allc=prv;
sort(a,a+tot,cmp);
for(int i=0;i<tot;i++)sz[a[i]]=1;
for(int i=0;i<tot;i++){
int f=0,s=a[i];
while(top>0){
f=lca(stk[top],s);
if(top>1&&dep[f]<dep[stk[top-1]]){
ins(stk[top],stk[top-1]);
ins(stk[top-1],stk[top]);
top--;
}
else if(dep[f]<dep[stk[top]]){
ins(stk[top],f);
ins(f,stk[top]);
top--;
break;
}
else break;
}
if(stk[top]!=f)stk[++top]=f;
stk[++top]=s;
}
while(top>1){
ins(stk[top],stk[top-1]);
ins(stk[top-1],stk[top]);
top--;
}
dfs1(a[0],0);
ans+=val*mul[K];
clear(a[0],0);
// printf("%I64d\n",val);
}
void dfs(int x,int f){
id[x]=++dfs_clock;
nxt[x][0]=f;
dep[x]=dep[f]+1;
for(int i=0;nxt[x][i];i++)
nxt[x][i+1]=nxt[nxt[x][i]][i];
for(int i=last[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(y!=f)dfs(y,x);
}
}
char mark[M];
int prm[M];
void pre(){
int cnt=0;
mul[1]=1;
for(int i=2;i<=Num;i++){
if(!mark[i]){
prm[cnt++]=i;
mul[i]=-1;
}
for(int j=0;j<cnt&&i*prm[j]<=Num;j++){
mark[i*prm[j]]=true;
if(i%prm[j]==0){
mul[i*prm[j]]=0;
break;
}
else mul[i*prm[j]]=-mul[i];
}
}
}
int main(){
scanf("%d",&n);
pre();
for(int i=0;i<20;i++)bin[i]=1<<i;
for(int v,i=1;i<=n;i++){
scanf("%d",&v);
ins_(v,i);
}
prv=allc;
for(int u,v,i=1;i<n;i++){
scanf("%d%d",&u,&v);
ins(u,v);ins(v,u);
}
//这里的边得到dfs序和深度以后就用不到了
dfs_clock=0;
dfs(1,0);
ans=0;
for(int i=1;i<=n;i++)
last[i]=0;
for(int i=1;i<=Num;i++)
if(mul[i])solve(i);
cout<<ans<<endl;
return 0;
}