#include <bits/stdc++.h>
using namespace std;
int prime[150000];
int lp[200010];
int phi[200010];
class prime_class {
 public:
  long top;
  prime_class() {
    int i, i2, j;
    top = 0;
    lp[0] = 0;
    lp[1] = 1;
    for (i = 2; i < 200010; i++) lp[i] = 0;
    top = 0;
    for (i = 2; i < 200010; ++i) {
      if (lp[i] == 0) {
        lp[i] = i;
        prime[top++] = i;
      }
      for (j = 0; (j < top) && (prime[j] <= lp[i]) && (i * prime[j] < 200010);
           ++j)
        lp[i * prime[j]] = prime[j];
    }
  }
  bool isprime(long long key) {
    if (key < 200010)
      return (lp[key] == key) && (key >= 2);
    else {
      int i;
      for (i = 0; (i < top) && (prime[i] * prime[i] <= key); i++)
        if (key % prime[i] == 0) return false;
      return true;
    }
  }
  unordered_map<int, int> factorize(int key) {
    unordered_map<int, int> ans;
    while (lp[key] != key) {
      ans[lp[key]]++;
      key /= lp[key];
    }
    if (key > 1) ans[key]++;
    return ans;
  }
  int get_phi(int key) {
    int ans = key, last = 0;
    while (lp[key] != key) {
      if (lp[key] != last) {
        last = lp[key];
        ans -= ans / last;
      }
      key /= lp[key];
    }
    if ((key > 1) && (key != last)) ans -= ans / key;
    return ans;
  }
  void calc_all_phi(int n) {
    int i, j, k;
    for (int i = 1; i < n; i++) phi[i] = i;
    for (int i = 2; i < n; i++) {
      if (phi[i] == i) {
        for (int j = i; j < n; j += i) {
          phi[j] /= i;
          phi[j] *= i - 1;
        }
      }
    }
  }
  vector<pair<long long, long long>> factorize_full(long long key) {
    vector<pair<long long, long long>> ans;
    long i, ct, sq = sqrt(key) + 10;
    for (i = 0; (i < top) && (prime[i] <= sq); i++)
      if (key % prime[i] == 0) {
        ct = 0;
        while (key % prime[i] == 0) {
          ct++;
          key /= prime[i];
        }
        ans.push_back({prime[i], ct});
      }
    if (key > 1) {
      ans.push_back({key, 1});
    }
    return ans;
  }
  void generate_divisors(int step, int v, vector<pair<int, int>>& fp,
                         vector<int>& ans) {
    if (step < fp.size()) {
      generate_divisors(step + 1, v, fp, ans);
      for (int i = 1; i <= fp[step].second; i++) {
        v *= fp[step].first;
        generate_divisors(step + 1, v, fp, ans);
      }
    } else
      ans.push_back(v);
  }
  void generate_divisors_full(long long step, long long v,
                              vector<pair<long long, long long>>& fp,
                              vector<long long>& ans) {
    if (step < fp.size()) {
      generate_divisors_full(step + 1, v, fp, ans);
      for (int i = 1; i <= fp[step].second; i++) {
        v *= fp[step].first;
        generate_divisors_full(step + 1, v, fp, ans);
      }
    } else
      ans.push_back(v);
  }
  vector<int> get_divisors(int key) {
    unordered_map<int, int> f = factorize(key);
    int n = f.size();
    vector<pair<int, int>> fp;
    for (auto p : f) fp.push_back(p);
    vector<int> ans;
    generate_divisors(0, 1, fp, ans);
    return ans;
  }
  vector<long long> get_divisors_full(long long key) {
    vector<pair<long long, long long>> f = factorize_full(key);
    int n = f.size();
    vector<pair<long long, long long>> fp;
    for (auto p : f) fp.push_back(p);
    vector<long long> ans;
    generate_divisors_full(0, 1, fp, ans);
    return ans;
  }
  long long get_divisors_count(long long key) {
    vector<pair<long long, long long>> f = factorize_full(key);
    long long ans = 1;
    for (auto p : f) ans *= (p.second + 1);
    return ans;
  }
};
class UnionFind {
 private:
  vector<int> p, rank, setSize;
  int numSets;

 public:
  UnionFind(int N) {
    setSize.assign(N, 1);
    numSets = N;
    rank.assign(N, 0);
    p.assign(N, 0);
    for (int i = 0; i < N; i++) p[i] = i;
  }
  int findSet(int i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); }
  bool isSameSet(int i, int j) { return findSet(i) == findSet(j); }
  void unionSet(int i, int j) {
    if (!isSameSet(i, j)) {
      numSets--;
      int x = findSet(i), y = findSet(j);
      if (rank[x] > rank[y]) {
        p[y] = x;
        setSize[x] += setSize[y];
      } else {
        p[x] = y;
        setSize[y] += setSize[x];
        if (rank[x] == rank[y]) rank[y]++;
      }
    }
  }
  int numDisjointSets() { return numSets; }
  int sizeOfSet(int i) { return setSize[findSet(i)]; }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  long long n, i, j, k, aa, bb, MAXX = 200010, x, m;
  prime_class pr;
  vector<vector<int>> d(MAXX);
  vector<int> mobius(MAXX);
  for (i = 1; i < MAXX; i++) d[i] = pr.get_divisors(i);
  for (i = 1; i < MAXX; i++) {
    unordered_map<int, int> f = pr.factorize(i);
    if (f.size() % 2 == 0)
      mobius[i] = 1;
    else
      mobius[i] = -1;
    for (auto p : f) {
      if (p.second >= 2) mobius[i] = 0;
    }
  }
  cin >> n;
  vector<int> a(n + 1);
  vector<vector<int>> plist(MAXX);
  for (i = 1; i <= n; i++) {
    cin >> a[i];
    for (auto p : d[a[i]]) plist[p].push_back(i);
  }
  vector<vector<int>> adj(n + 1);
  for (i = 0; i < n - 1; i++) {
    cin >> aa >> bb;
    adj[aa].push_back(bb);
  }
  vector<int> last(n + 1, -1), cid(n + 1, -1);
  vector<long long> ans(MAXX, 0), h(MAXX, 0);
  for (i = 1; i < MAXX; i++) {
    m = plist[i].size();
    for (j = 0; j < m; j++) {
      int id = plist[i][j];
      last[id] = i;
      cid[id] = j;
    }
    UnionFind uf(m);
    for (j = 0; j < m; j++) {
      int id = plist[i][j];
      for (auto v : adj[id]) {
        if (last[v] == i) uf.unionSet(j, cid[v]);
      }
    }
    for (j = 0; j < m; j++) {
      if (uf.findSet(j) == j) {
        x = uf.sizeOfSet(j);
        h[i] += x * (x + 1) / 2;
      }
    }
  }
  for (i = 1; i < MAXX; i++) {
    x = 0;
    for (j = i; j < MAXX; j += i) {
      ++x;
      if (mobius[x] == 1)
        ans[i] += h[j];
      else if (mobius[x] == -1)
        ans[i] -= h[j];
    }
  }
  for (i = 1; i < MAXX; i++) {
    if (ans[i] > 0) cout << i << " " << ans[i] << "\n";
  }
  return 0;
}
