#include <bits/stdc++.h>
using namespace std;
struct Edge {
  int to, nxt;
} E[500005 * 2];
int Head[500005], tot, x, y, z, V[500005], prime[500005], n, primenum, lim,
    maxans, f[500005], ans[500005], max1, max2, maxv;
bool vis[500005], isprime[500005], dp[500005], skip;
void addedge(int x, int y) {
  E[++tot] = (Edge){y, Head[x]};
  Head[x] = tot;
}
void getprime() {
  lim = 500005;
  memset(isprime, true, sizeof(isprime));
  for (int i = 2; i < lim; i++) {
    if (isprime[i]) prime[++primenum] = i;
    for (int j = 2; j <= (lim / i); j++) isprime[i * j] = false;
  }
}
void read() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%d", &V[i]), maxv = max(maxv, V[i]);
  for (int i = 1; i < n; i++) {
    scanf("%d%d", &x, &y);
    addedge(x, y);
    addedge(y, x);
  }
}
void dfs(int v, int fa) {
  vis[v] = true;
  if (!dp[v]) return;
  f[v] = 1;
  int max1 = 0, max2 = 0;
  for (int i = Head[v]; i; i = E[i].nxt) {
    if (E[i].to == fa) continue;
    dfs(E[i].to, v);
    f[v] = max(f[E[i].to] + 1, f[v]);
    if (f[E[i].to] > max1) {
      max2 = max1;
      max1 = f[E[i].to];
    } else {
      max2 = max(max2, f[E[i].to]);
    }
  }
  ans[v] = max1 + max2 + 1;
  maxans = max(maxans, ans[v]);
}
void solve() {
  maxans = 0;
  if (maxv < 2) {
    printf("0\n");
    return;
  }
  for (int p = 1; p <= 650; p++) {
    if (prime[p] > maxv) break;
    memset(vis, false, sizeof(vis));
    memset(f, 0, sizeof(f));
    memset(ans, 0, sizeof(ans));
    for (int i = 1; i <= n; i++) dp[i] = !(V[i] % prime[p]);
    for (int i = 1; i <= n; i++) {
      if (!vis[i]) dfs(i, 0);
    }
  }
  memset(vis, false, sizeof(vis));
  memset(f, 0, sizeof(f));
  memset(ans, 0, sizeof(ans));
  for (int i = 1; i <= n; i++) dp[i] = !(V[i] % maxv);
  for (int i = 1; i <= n; i++) {
    if (!vis[i]) dfs(i, 0);
  }
  printf("%d\n", maxans);
}
int main() {
  getprime();
  read();
  solve();
  return 0;
}
