#include <bits/stdc++.h>
const int mod = 1000000007;
using LL = long long;
namespace tree {
struct edge {
  int to, nxt;
} e[200005 << 1];
int head[200005], tot, n, a[200005], f[18][200005], dep[200005], idx,
    dfn[200005];
void addedge(int x, int y) {
  e[++tot] = (edge){y, head[x]};
  head[x] = tot;
  e[++tot] = (edge){x, head[y]};
  head[y] = tot;
}
void dfs0(int x) {
  dfn[x] = ++idx;
  for (int i = 1; i < 18; i++) f[i][x] = f[i - 1][f[i - 1][x]];
  for (int i = head[x]; i; i = e[i].nxt)
    if (e[i].to != f[0][x])
      f[0][e[i].to] = x, dep[e[i].to] = dep[x] + 1, dfs0(e[i].to);
}
int lca(int x, int y) {
  if (dep[x] < dep[y]) std::swap(x, y);
  for (int i = dep[x] - dep[y]; i; i &= i - 1) x = f[__builtin_ctz(i)][x];
  for (int i = 17; i + 1; i--)
    if (f[i][x] != f[i][y]) x = f[i][x], y = f[i][y];
  return x == y ? x : f[0][x];
}
}  // namespace tree
void up(int &x, int y) {
  if ((x += y) >= mod) x -= mod;
}
namespace number {
int phi[200005], miu[200005], pr[200005], pt, F[200005], inv[200005],
    sie[200005];
int pow(int x, int y) {
  int ans = 1;
  for (; y; y >>= 1, x = static_cast<LL>(x) * x % mod)
    if (y & 1) ans = static_cast<LL>(ans) * x % mod;
  return ans;
}
void sieve(int R) {
  phi[1] = miu[1] = 1;
  for (int i = 2; i <= R; i++) {
    if (!sie[i]) phi[i] = i - 1, miu[i] = mod - 1, pr[++pt] = i;
    for (int j = 1, t; j <= pt && (t = i * pr[j]) <= R; j++) {
      sie[t] = 1;
      if (i % pr[j] == 0) {
        phi[t] = phi[i] * pr[j], miu[t] = 0;
        break;
      }
      phi[t] = phi[i] * (pr[j] - 1), up(miu[t] = 0, mod - miu[i]);
    }
  }
  inv[1] = 1;
  for (int i = 2; i <= R; i++)
    inv[i] = static_cast<LL>(inv[mod % i]) * (mod - mod / i) % mod;
  for (int i = 1; i <= R; i++)
    for (int j = i, t = 1; j <= R; j += i, t++)
      up(F[j], static_cast<LL>(i) * inv[phi[i]] % mod * miu[t] % mod);
}
}  // namespace number
namespace vtree {
int head[200005], tot, size[200005], val[200005], sum = 0, ans = 0;
struct edge {
  int to, nxt, len;
} e[200005 << 1];
void addedge(int x, int y, int z) {
  e[++tot] = (edge){y, head[x], z};
  head[x] = tot;
  e[++tot] = (edge){x, head[y], z};
  head[y] = tot;
}
void addedge(int x, int y) {
  addedge(x, y, std::abs(tree::dep[x] - tree::dep[y]));
}
int dfs0(int x, int f) {
  size[x] = 0;
  for (int i = head[x]; i; i = e[i].nxt)
    if (e[i].to != f)
      up(size[x], dfs0(e[i].to, x)),
          up(ans, static_cast<LL>(size[e[i].to]) * (sum - size[e[i].to] + mod) %
                      mod * e[i].len * 2 % mod);
  up(size[x], val[x]);
  val[x] = 0;
  head[x] = 0;
  return size[x];
}
}  // namespace vtree
int query[200005], ans, stack[200005], top, n, a[200005], map[200005], x, y;
int main() {
  std::scanf("%d", &n);
  for (int i = 1; i <= n; i++) std::scanf("%d", &a[i]), map[a[i]] = i;
  for (int i = 1; i < n; i++) std::scanf("%d%d", &x, &y), tree::addedge(x, y);
  number::sieve(n), tree::dfs0(1);
  for (int i = 1; i <= n; i++) {
    int tot = 0;
    vtree::sum = vtree::ans = vtree::tot = 0;
    for (int j = i; j <= n; j += i)
      query[++tot] = map[j], up(vtree::sum, number::phi[j]),
      vtree::val[map[j]] = number::phi[j];
    std::sort(query + 1, query + tot + 1,
              [](int i, int j) { return tree::dfn[i] < tree::dfn[j]; });
    int rt = query[1];
    for (int j = 2; j <= tot; j++) rt = tree::lca(rt, query[j]);
    stack[top = 1] = rt;
    for (int j = 1; j <= tot; j++) {
      int lca = tree::lca(query[j], stack[top]);
      while (tree::dep[lca] < tree::dep[stack[top - 1]])
        vtree::addedge(stack[top], stack[top - 1]), --top;
      if (lca != stack[top]) vtree::addedge(lca, stack[top--]);
      if (stack[top] != lca) stack[++top] = lca;
      if (stack[top] != query[j]) stack[++top] = query[j];
    }
    while (--top) vtree::addedge(stack[top + 1], stack[top]);
    vtree::dfs0(rt, 0);
    up(ans, static_cast<LL>(number::F[i]) * vtree::ans % mod);
  }
  std::printf("%d\n",
              static_cast<LL>(ans) *
                  number::pow(static_cast<LL>(n) * (n - 1) % mod, mod - 2) %
                  mod);
  return 0;
}
