#include <bits/stdc++.h>
class dsu {
  int fa[200005], sz[200005];

 public:
  void init(int pos) {
    fa[pos] = -1;
    sz[pos] = 1;
  }
  int query_root(int pos) {
    return fa[pos] == -1 ? pos : (fa[pos] = query_root(fa[pos]));
  }
  int query_size(int pos) { return sz[query_root(pos)]; }
  void merge(int pa, int child) {
    pa = query_root(pa);
    child = query_root(child);
    if (pa != child) {
      fa[child] = pa;
      sz[pa] += sz[child];
    }
  }
};
dsu du;
int a[200005], maxa;
std::vector<int> nodes[200005];
std::vector<int> adj[200005];
int64_t ans[200005];
int n;
int main(int argc, char* argv[]) {
  scanf("%d", &n);
  for (int i = 1; i <= n; ++i) {
    scanf("%d", &a[i]);
    nodes[a[i]].push_back(i);
    maxa = std::max(maxa, a[i]);
  }
  for (int i = 1; i < n; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    adj[x].push_back(y);
    adj[y].push_back(x);
  }
  for (int i = maxa; i > 0; --i) {
    int64_t& nowans = ans[i];
    std::vector<int> rd;
    for (int j = i; j <= maxa; j += i) {
      for (int nd : nodes[j]) du.init(nd);
      rd.insert(rd.end(), nodes[j].begin(), nodes[j].end());
    }
    for (int nd : rd) {
      for (int nxt : adj[nd]) {
        if (a[nxt] % i)
          continue;
        else {
          if (du.query_root(nd) != du.query_root(nxt)) {
            nowans += (int64_t)du.query_size(nd) * du.query_size(nxt);
            du.merge(nd, nxt);
          }
        }
      }
    }
    for (int j = i + i; j <= maxa; j += i) nowans -= ans[j];
  }
  for (int i = 1; i <= maxa; ++i) ans[i] += nodes[i].size();
  for (int i = 1; i <= maxa; ++i) {
    if (ans[i]) printf("%d %lld\n", i, ans[i]);
  }
  return 0;
}
