#include <bits/stdc++.h>
using namespace std;
char getc() {
  char c = getchar();
  while ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && (c < '0' || c > '9'))
    c = getchar();
  return c;
}
int gcd(int n, int m) { return m == 0 ? n : gcd(m, n % m); }
int read() {
  int x = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9')
    x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
  return x * f;
}
int n, a[200010], p[200010], t;
int prime[200010], phi[200010], mobius[200010], inv[200010], cnt;
int deep[200010], size[200010], val[200010], f[200010], ans;
bool flag[200010];
vector<int> factor[200010];
struct data {
  int to, nxt;
} edge[200010 << 1];
void addedge(int x, int y) {
  t++;
  edge[t].to = y, edge[t].nxt = p[x], p[x] = t;
}
inline void inc(int &x, int y) {
  x += y;
  if (x >= 1000000007) x -= 1000000007;
}
void make(int k, int from) {
  size[k] = 1;
  for (int i = p[k]; i; i = edge[i].nxt)
    if (!flag[edge[i].to] && edge[i].to != from) {
      deep[edge[i].to] = deep[k] + 1;
      make(edge[i].to, k);
      size[k] += size[edge[i].to];
    }
}
int findroot(int k, int from, int s) {
  int mx = 0;
  for (int i = p[k]; i; i = edge[i].nxt)
    if (!flag[edge[i].to] && edge[i].to != from && size[edge[i].to] > size[mx])
      mx = edge[i].to;
  if ((size[mx] << 1) > s)
    return findroot(mx, k, s);
  else
    return k;
}
void work(int k, int from, int op) {
  for (int i = 0; i < factor[a[k]].size(); i++)
    if (op == 1)
      inc(val[factor[a[k]][i]], phi[a[k]]);
    else
      inc(val[factor[a[k]][i]], 1000000007 - phi[a[k]]);
  for (int i = p[k]; i; i = edge[i].nxt)
    if (!flag[edge[i].to] && edge[i].to != from) work(edge[i].to, k, op);
}
void update(int k, int from) {
  for (int i = 0; i < factor[a[k]].size(); i++)
    inc(f[factor[a[k]][i]], 2ll * deep[k] * phi[a[k]] % 1000000007 *
                                val[factor[a[k]][i]] % 1000000007);
  for (int i = p[k]; i; i = edge[i].nxt)
    if (!flag[edge[i].to] && edge[i].to != from) update(edge[i].to, k);
}
void solve(int k) {
  make(k, k);
  k = findroot(k, k, size[k]);
  flag[k] = 1;
  deep[k] = 0;
  make(k, k);
  work(k, k, 1);
  for (int i = p[k]; i; i = edge[i].nxt)
    if (!flag[edge[i].to]) {
      work(edge[i].to, edge[i].to, -1);
      update(edge[i].to, edge[i].to);
      work(edge[i].to, edge[i].to, 1);
    }
  work(k, k, -1);
  for (int i = p[k]; i; i = edge[i].nxt)
    if (!flag[edge[i].to]) solve(edge[i].to);
}
signed main() {
  n = read();
  for (int i = 1; i <= n; i++) a[i] = read();
  for (int i = 1; i < n; i++) {
    int x = read(), y = read();
    addedge(x, y), addedge(y, x);
  }
  flag[1] = 1;
  mobius[1] = phi[1] = 1;
  for (int i = 2; i <= n; i++) {
    if (!flag[i]) prime[++cnt] = i, mobius[i] = -1, phi[i] = i - 1;
    for (int j = 1; j <= cnt && prime[j] * i <= n; j++) {
      flag[prime[j] * i] = 1;
      if (i % prime[j] == 0) {
        phi[prime[j] * i] = phi[i] * prime[j];
        break;
      }
      mobius[prime[j] * i] = -mobius[i];
      phi[prime[j] * i] = phi[i] * (prime[j] - 1);
    }
  }
  inv[1] = 1;
  for (int i = 2; i <= n; i++)
    inv[i] =
        1000000007 - 1ll * (1000000007 / i) * inv[1000000007 % i] % 1000000007;
  memset(flag, 0, sizeof(flag));
  for (int i = 1; i <= n; i++)
    for (int j = i; j <= n; j += i) factor[j].push_back(i);
  solve(1);
  for (int i = 1; i <= n; i++)
    for (int j = i; j <= n; j += i)
      ans = (ans + 1ll * f[j] * (1000000007 + mobius[j / i]) % 1000000007 * i %
                       1000000007 * inv[phi[i]]) %
            1000000007;
  cout << 1ll * ans * inv[n] % 1000000007 * inv[n - 1] % 1000000007;
  return 0;
}
