#include <bits/stdc++.h>
using namespace std;
vector<unordered_map<long long, long long>> dists(200002);
vector<long long> siv(200002), A(200002);
long long maxi = 0;
void euler_sieve() {
  long long n = siv.size();
  for (long long i = 0; i < n; i++) siv[i] = i;
  for (long long i = 2; i <= sqrt(n); i++) {
    if (siv[i] == i) {
      for (long long j = i * i; j < n; j += i)
        if (siv[j] == j) siv[j] = i;
    }
  }
}
vector<long long> prime_factors_euler(long long num) {
  long long n = siv.size();
  if (siv[num] == num) return vector<long long>{num};
  vector<long long> res;
  while (siv[num] != num) {
    res.push_back(siv[num]);
    num /= siv[num];
  }
  res.push_back(siv[num]);
  return res;
}
void update(pair<long long, long long> &t, long long val) {
  if (val > t.first) {
    t.second = t.first;
    t.first = val;
  } else
    t.second = max(t.second, val);
}
void dfs_tree(long long idx, long long par, vector<vector<long long>> &adj) {
  set<long long> pr;
  auto vec = prime_factors_euler(A[idx]);
  for (auto i : vec) pr.insert(i);
  for (auto i : pr) {
    if (i == 1) continue;
    dists[idx][i] = 1;
  }
  for (auto i : adj[idx]) {
    if (i != par) {
      dfs_tree(i, idx, adj);
    }
  }
  for (auto j : pr) {
    if (j == 1) continue;
    pair<long long, long long> t = {0, 0};
    for (auto i : adj[idx]) {
      if (i != par) {
        if (dists[i].find(j) != dists[i].end()) update(t, dists[i][j]);
      }
    }
    maxi = max(maxi, dists[idx][j] + t.first + t.second);
    dists[idx][j] += max(t.first, t.second);
  }
}
int main() {
  euler_sieve();
  long long(n);
  scanf("%lld", &(n));
  ;
  for (long long i = 0; i < (n); i++) {
    long long(a);
    scanf("%lld", &(a));
    ;
    A[i] = a;
  }
  vector<vector<long long>> adj(n);
  for (long long i = 0; i < n - 1; i++) {
    long long a, b;
    scanf("%lld %lld", &a, &b);
    adj[a - 1].push_back(b - 1);
    adj[b - 1].push_back(a - 1);
  };
  dfs_tree(0, -1, adj);
  printf("%lld\n", maxi);
  return 0;
}
