#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
template<typename T>
ostream &operator<<(ostream &out, const vector<T> &arr) {
	out << "[";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "]";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const map<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x.first << " => " << x.second;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const multimap<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x.first << " => " << x.second;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const set<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const multiset<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "}";
	return out;
}

#define debug(...) __debugg(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __debuggg(Arg1 &&arg1) {
	cout << " : " << arg1;
}

void __debuggg([[gnu::unused]] const char *arg1) { }

template <typename Arg1>
void __debugg(const char *name, Arg1 &&arg1) {
	cout << name;
	__debuggg(arg1);
	cout << std::endl;
}

template <typename Arg1, typename... Args>
void __debugg(const char *names, Arg1 &&arg1, Args &&... args) {
	const char *comma = names;
	int gyl = 0;

	while (*comma != ',' or gyl > 0) {
		if (*comma == '(' or * comma == '{' or * comma == '[')
			gyl++;

		if (*comma == ')' or * comma == '}' or * comma == ']')
			gyl--;

		comma++;
	}

	cout.write(names, comma - names);
	__debuggg(arg1);
	cout << " | ";

	if (*(comma + 1) == ' ')
		comma++;

	__debugg(comma + 1, args...);
}
#else
#define debug(...)
#endif

template<typename X, typename Y>
struct Pair {
	X x;
	Y y;
	template<typename X1, typename Y1>
	Pair(const X1 &x, const Y1 &y): x(x), y(y) {}
	Pair() {}
	template<typename X1>
	explicit Pair(const X1 &x): x(x), y(Y()) {}
	template<typename X1, typename Y1>
	Pair<X, Y> operator+(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x + o.x, y + o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator-(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x - o.x, y - o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator*(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x * o.x, y * o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator/(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x / o.x, y / o.y);
	}
	template<typename X1, typename Y1>
	void operator+=(const Pair<X1, Y1> &o) {
		x += o.x;
		y += o.y;
	}
	template<typename X1, typename Y1>
	void operator-=(const Pair<X1, Y1> &o) {
		x -= o.x;
		y -= o.y;
	}
	template<typename X1, typename Y1>
	void operator*=(const Pair<X1, Y1> &o) {
		x *= o.x;
		y *= o.y;
	}
	template<typename X1, typename Y1>
	void operator/=(const Pair<X1, Y1> &o) {
		x /= o.x;
		y /= o.y;
	}
	template<typename X1, typename Y1>
	bool operator<(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y < o.y;

		return x < o.x;
	}
	template<typename X1, typename Y1>
	bool operator<=(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y <= o.y;

		return x <= o.x;
	}
	template<typename X1, typename Y1>
	bool operator>(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y > o.y;

		return x > o.x;
	}
	template<typename X1, typename Y1>
	bool operator>=(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y >= o.y;

		return x >= o.x;
	}
	template<typename X1, typename Y1>
	bool operator==(const Pair<X1, Y1> &o)const {
		return x == o.x and y == o.y;
	}
	template<typename X1, typename Y1>
	bool operator!=(const Pair<X1, Y1> &o)const {
		return x != o.x or y != o.y;
	}
	template<typename X1, typename Y1>
	void swap(Pair<X1, Y1> &o) {
		swap(x, o.x);
		swap(y, o.y);
	}
};

template<typename X, typename Y>
Pair<X, Y> makep(const X &x, const Y &y) {
	return Pair<X, Y>(x, y);
}

template<typename X, typename Y>
ostream &operator<<(ostream &out, const Pair<X, Y> &p) {
	out << "(" << p.x << ", " << p.y << ")";
	return out;
}

template<typename X, typename Y>
istream &operator>>(istream &in, Pair<X, Y> &p) {
	in >> p.x >> p.y;
	return in;
}

#define pair Pair

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef Pair<int, int> pii;
typedef Pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef vector<pii> vpii;

template<typename T>
istream &operator>>(istream &in, vector<T> &arr) {
	for (auto && x : arr) {
		in >> x;
	}

	return in;
}

template<typename X, typename Y>
inline X mini(X &a, const Y &b) __attribute__((always_inline));
template<typename X, typename Y>
inline X mini(X &a, const Y &b) {
	if (a > b)
		a = b;

	return a;
}
template<typename X, typename Y>
inline X maxi(X &a, const Y &b) __attribute__((always_inline));
template<typename X, typename Y>
inline X maxi(X &a, const Y &b) {
	if (a < b)
		a = b;

	return a;
}

/*link https://codeforces.com/contest/990/problem/G */
/*input
3
1 2 3
1 2
2 3
*/
/*output
1 4
2 1
3 1
*/
/*input
6
1 2 4 8 16 32
1 6
6 3
3 4
4 2
6 5
*/
/*output
1 6
2 5
4 6
8 1
16 2
32 1
*/
/*input
4
9 16 144 6
1 3
2 3
4 3
*/
/*output
1 1
2 1
3 1
6 2
9 2
16 2
144 1
*/

ll gcd(ll a, ll b) {
	if (a > b)
		swap(a, b);

	if (a == 0)
		return b;

	return gcd(b % a, a);
}

vector<bool> apl;
vector<bool> apl2;
vector<int> gra[200000];
int n;
ll m;
vi ats;
vi dyd;
vi gyl;
vi a;
set<int> pask;
vi idom;
vi kiek;
const int lima = 200001;
int raskdyd(int d, int p) {
	apl2[d] = true;
	dyd[d] = 1;

	for (auto && i : gra[d]) {
		if (i == p or apl[i])
			continue;

		dyd[d] += raskdyd(i, d);
	}

	return dyd[d];
}
void raskgyl(int d, int p, ll dal = 0) {
	dal = gcd(a[d], dal);
	pask.insert(dal);
	kiek[dal]++;

	for (auto && i : gra[d]) {
		if (i == p or apl[i])
			continue;

		raskgyl(i, d, dal);
	}
}
int ieskok(int d, int p, int didz) {
	for (auto && i : gra[d]) {
		if (i == p or apl[i])
			continue;

		if (dyd[i] > didz)
			return ieskok(i, d, didz);
	}

	return d;
}
int main () {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n;
	a.resize(n);
	cin >> a;
	apl = vector<bool>(n, false);
	dyd = vi(n, 0);
	gyl = vi(n, 0);
	ats = vi(lima, 0);

	for (int i = 0; i < n - 1; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		gra[a].push_back(b);
		gra[b].push_back(a);
	}

	while (true) {
		bool rad = false;
		apl2 = vector<bool>(n, false);
		vi kiek2 = vi(200000, 0);
		kiek = vi(200000, 0);

		for (int i = 0; i < n; i++) {
			if (!apl[i] and !apl2[i]) {
				int dydis = raskdyd(i, -1);
				int cent = ieskok(i, -1, dydis / 2);

				ats[a[cent]]++;
				kiek2[a[cent]]++;
				set<int> idom;
				idom.insert(a[cent]);

				for (auto && j : gra[cent]) {
					if (apl[j])
						continue;

					pask.clear();
					raskgyl(j, cent, a[cent]);

					debug(pask, idom);

					for (auto && i : pask) {
						for (auto && j : idom) {
							ats[gcd(i, j)] += kiek2[j] * kiek[i];
						}
					}

					for (auto && i : pask) {
						idom.insert(i);
						kiek2[i] += kiek[i];
						kiek[i] = 0;
					}
				}

				for (auto && i : idom) {
					kiek2[i] = 0;
				}

				rad = true;
				apl[cent] = true;
			}
		}

		if (!rad)
			break;
	}

	for (int i = 1; i < lima; i++) {
		if (ats[i])
			cout << i << " " << ats[i] << "\n";
	}

}


#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
template<typename T>
ostream &operator<<(ostream &out, const vector<T> &arr) {
	out << "[";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "]";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const map<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x.first << " => " << x.second;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const multimap<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x.first << " => " << x.second;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const set<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const multiset<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "}";
	return out;
}

#define debug(...) __debugg(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __debuggg(Arg1 &&arg1) {
	cout << " : " << arg1;
}

void __debuggg([[gnu::unused]] const char *arg1) { }

template <typename Arg1>
void __debugg(const char *name, Arg1 &&arg1) {
	cout << name;
	__debuggg(arg1);
	cout << std::endl;
}

template <typename Arg1, typename... Args>
void __debugg(const char *names, Arg1 &&arg1, Args &&... args) {
	const char *comma = names;
	int gyl = 0;

	while (*comma != ',' or gyl > 0) {
		if (*comma == '(' or * comma == '{' or * comma == '[')
			gyl++;

		if (*comma == ')' or * comma == '}' or * comma == ']')
			gyl--;

		comma++;
	}

	cout.write(names, comma - names);
	__debuggg(arg1);
	cout << " | ";

	if (*(comma + 1) == ' ')
		comma++;

	__debugg(comma + 1, args...);
}
#else
#define debug(...)
#endif

template<typename X, typename Y>
struct Pair {
	X x;
	Y y;
	template<typename X1, typename Y1>
	Pair(const X1 &x, const Y1 &y): x(x), y(y) {}
	Pair() {}
	template<typename X1>
	explicit Pair(const X1 &x): x(x), y(Y()) {}
	template<typename X1, typename Y1>
	Pair<X, Y> operator+(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x + o.x, y + o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator-(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x - o.x, y - o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator*(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x * o.x, y * o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator/(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x / o.x, y / o.y);
	}
	template<typename X1, typename Y1>
	void operator+=(const Pair<X1, Y1> &o) {
		x += o.x;
		y += o.y;
	}
	template<typename X1, typename Y1>
	void operator-=(const Pair<X1, Y1> &o) {
		x -= o.x;
		y -= o.y;
	}
	template<typename X1, typename Y1>
	void operator*=(const Pair<X1, Y1> &o) {
		x *= o.x;
		y *= o.y;
	}
	template<typename X1, typename Y1>
	void operator/=(const Pair<X1, Y1> &o) {
		x /= o.x;
		y /= o.y;
	}
	template<typename X1, typename Y1>
	bool operator<(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y < o.y;

		return x < o.x;
	}
	template<typename X1, typename Y1>
	bool operator<=(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y <= o.y;

		return x <= o.x;
	}
	template<typename X1, typename Y1>
	bool operator>(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y > o.y;

		return x > o.x;
	}
	template<typename X1, typename Y1>
	bool operator>=(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y >= o.y;

		return x >= o.x;
	}
	template<typename X1, typename Y1>
	bool operator==(const Pair<X1, Y1> &o)const {
		return x == o.x and y == o.y;
	}
	template<typename X1, typename Y1>
	bool operator!=(const Pair<X1, Y1> &o)const {
		return x != o.x or y != o.y;
	}
	template<typename X1, typename Y1>
	void swap(Pair<X1, Y1> &o) {
		swap(x, o.x);
		swap(y, o.y);
	}
};

template<typename X, typename Y>
Pair<X, Y> makep(const X &x, const Y &y) {
	return Pair<X, Y>(x, y);
}

template<typename X, typename Y>
ostream &operator<<(ostream &out, const Pair<X, Y> &p) {
	out << "(" << p.x << ", " << p.y << ")";
	return out;
}

template<typename X, typename Y>
istream &operator>>(istream &in, Pair<X, Y> &p) {
	in >> p.x >> p.y;
	return in;
}

#define pair Pair

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef Pair<int, int> pii;
typedef Pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef vector<pii> vpii;

template<typename T>
istream &operator>>(istream &in, vector<T> &arr) {
	for (auto && x : arr) {
		in >> x;
	}

	return in;
}

template<typename X, typename Y>
inline X mini(X &a, const Y &b) __attribute__((always_inline));
template<typename X, typename Y>
inline X mini(X &a, const Y &b) {
	if (a > b)
		a = b;

	return a;
}
template<typename X, typename Y>
inline X maxi(X &a, const Y &b) __attribute__((always_inline));
template<typename X, typename Y>
inline X maxi(X &a, const Y &b) {
	if (a < b)
		a = b;

	return a;
}

/*link https://codeforces.com/contest/990/problem/G */
/*input
3
1 2 3
1 2
2 3
*/
/*output
1 4
2 1
3 1
*/
/*input
6
1 2 4 8 16 32
1 6
6 3
3 4
4 2
6 5
*/
/*output
1 6
2 5
4 6
8 1
16 2
32 1
*/
/*input
4
9 16 144 6
1 3
2 3
4 3
*/
/*output
1 1
2 1
3 1
6 2
9 2
16 2
144 1
*/

ll gcd(ll a, ll b) {
	if (a > b)
		swap(a, b);

	if (a == 0)
		return b;

	return gcd(b % a, a);
}

vector<bool> apl;
vector<bool> apl2;
vector<int> gra[200000];
int n;
ll m;
vll ats;
vi dyd;
vi gyl;
vi a;
set<int> pask;
vi idom;
vi kiek;
const int lima = 200001;
int raskdyd(int d, int p) {
	apl2[d] = true;
	dyd[d] = 1;

	for (auto && i : gra[d]) {
		if (i == p or apl[i])
			continue;

		dyd[d] += raskdyd(i, d);
	}

	return dyd[d];
}
void raskgyl(int d, int p, ll dal = 0) {
	dal = gcd(a[d], dal);
	pask.insert(dal);
	kiek[dal]++;

	for (auto && i : gra[d]) {
		if (i == p or apl[i])
			continue;

		raskgyl(i, d, dal);
	}
}
int ieskok(int d, int p, int didz) {
	for (auto && i : gra[d]) {
		if (i == p or apl[i])
			continue;

		if (dyd[i] > didz)
			return ieskok(i, d, didz);
	}

	return d;
}
int main () {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n;
	a.resize(n);
	cin >> a;
	apl = vector<bool>(n, false);
	dyd = vi(n, 0);
	gyl = vi(n, 0);
	ats = vll(lima, 0);

	for (int i = 0; i < n - 1; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		gra[a].push_back(b);
		gra[b].push_back(a);
	}

	while (true) {
		bool rad = false;
		apl2 = vector<bool>(n, false);
		vi kiek2 = vi(200000, 0);
		kiek = vi(200000, 0);

		for (int i = 0; i < n; i++) {
			if (!apl[i] and !apl2[i]) {
				int dydis = raskdyd(i, -1);
				int cent = ieskok(i, -1, dydis / 2);

				ats[a[cent]]++;
				kiek2[a[cent]]++;
				set<int> idom;
				idom.insert(a[cent]);

				for (auto && j : gra[cent]) {
					if (apl[j])
						continue;

					pask.clear();
					raskgyl(j, cent, a[cent]);

					debug(pask, idom);

					for (auto && i : pask) {
						for (auto && j : idom) {
							ats[gcd(i, j)] += kiek2[j] * 1ll * kiek[i];
						}
					}

					for (auto && i : pask) {
						idom.insert(i);
						kiek2[i] += kiek[i];
						kiek[i] = 0;
					}
				}

				for (auto && i : idom) {
					kiek2[i] = 0;
				}

				rad = true;
				apl[cent] = true;
			}
		}

		if (!rad)
			break;
	}

	for (int i = 1; i < lima; i++) {
		if (ats[i])
			cout << i << " " << ats[i] << "\n";
	}

}


#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
template<typename T>
ostream &operator<<(ostream &out, const vector<T> &arr) {
	out << "[";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "]";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const map<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x.first << " => " << x.second;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const multimap<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x.first << " => " << x.second;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const set<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "}";
	return out;
}

template<typename T, typename P>
ostream &operator<<(ostream &out, const multiset<T, P> &arr) {
	out << "{";
	bool buv = false;

	for (auto && x : arr) {
		if (buv)
			out << ", ";

		out << x;
		buv = true;
	}

	out << "}";
	return out;
}

#define debug(...) __debugg(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __debuggg(Arg1 &&arg1) {
	cout << " : " << arg1;
}

void __debuggg([[gnu::unused]] const char *arg1) { }

template <typename Arg1>
void __debugg(const char *name, Arg1 &&arg1) {
	cout << name;
	__debuggg(arg1);
	cout << std::endl;
}

template <typename Arg1, typename... Args>
void __debugg(const char *names, Arg1 &&arg1, Args &&... args) {
	const char *comma = names;
	int gyl = 0;

	while (*comma != ',' or gyl > 0) {
		if (*comma == '(' or * comma == '{' or * comma == '[')
			gyl++;

		if (*comma == ')' or * comma == '}' or * comma == ']')
			gyl--;

		comma++;
	}

	cout.write(names, comma - names);
	__debuggg(arg1);
	cout << " | ";

	if (*(comma + 1) == ' ')
		comma++;

	__debugg(comma + 1, args...);
}
#else
#define debug(...)
#endif

template<typename X, typename Y>
struct Pair {
	X x;
	Y y;
	template<typename X1, typename Y1>
	Pair(const X1 &x, const Y1 &y): x(x), y(y) {}
	Pair() {}
	template<typename X1>
	explicit Pair(const X1 &x): x(x), y(Y()) {}
	template<typename X1, typename Y1>
	Pair<X, Y> operator+(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x + o.x, y + o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator-(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x - o.x, y - o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator*(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x * o.x, y * o.y);
	}
	template<typename X1, typename Y1>
	Pair<X, Y> operator/(const Pair<X1, Y1> &o)const {
		return Pair<X1, Y1>(x / o.x, y / o.y);
	}
	template<typename X1, typename Y1>
	void operator+=(const Pair<X1, Y1> &o) {
		x += o.x;
		y += o.y;
	}
	template<typename X1, typename Y1>
	void operator-=(const Pair<X1, Y1> &o) {
		x -= o.x;
		y -= o.y;
	}
	template<typename X1, typename Y1>
	void operator*=(const Pair<X1, Y1> &o) {
		x *= o.x;
		y *= o.y;
	}
	template<typename X1, typename Y1>
	void operator/=(const Pair<X1, Y1> &o) {
		x /= o.x;
		y /= o.y;
	}
	template<typename X1, typename Y1>
	bool operator<(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y < o.y;

		return x < o.x;
	}
	template<typename X1, typename Y1>
	bool operator<=(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y <= o.y;

		return x <= o.x;
	}
	template<typename X1, typename Y1>
	bool operator>(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y > o.y;

		return x > o.x;
	}
	template<typename X1, typename Y1>
	bool operator>=(const Pair<X1, Y1> &o)const {
		if (x == o.x)
			return y >= o.y;

		return x >= o.x;
	}
	template<typename X1, typename Y1>
	bool operator==(const Pair<X1, Y1> &o)const {
		return x == o.x and y == o.y;
	}
	template<typename X1, typename Y1>
	bool operator!=(const Pair<X1, Y1> &o)const {
		return x != o.x or y != o.y;
	}
	template<typename X1, typename Y1>
	void swap(Pair<X1, Y1> &o) {
		swap(x, o.x);
		swap(y, o.y);
	}
};

template<typename X, typename Y>
Pair<X, Y> makep(const X &x, const Y &y) {
	return Pair<X, Y>(x, y);
}

template<typename X, typename Y>
ostream &operator<<(ostream &out, const Pair<X, Y> &p) {
	out << "(" << p.x << ", " << p.y << ")";
	return out;
}

template<typename X, typename Y>
istream &operator>>(istream &in, Pair<X, Y> &p) {
	in >> p.x >> p.y;
	return in;
}

#define pair Pair

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef Pair<int, int> pii;
typedef Pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef vector<pii> vpii;

template<typename T>
istream &operator>>(istream &in, vector<T> &arr) {
	for (auto && x : arr) {
		in >> x;
	}

	return in;
}

template<typename X, typename Y>
inline X mini(X &a, const Y &b) __attribute__((always_inline));
template<typename X, typename Y>
inline X mini(X &a, const Y &b) {
	if (a > b)
		a = b;

	return a;
}
template<typename X, typename Y>
inline X maxi(X &a, const Y &b) __attribute__((always_inline));
template<typename X, typename Y>
inline X maxi(X &a, const Y &b) {
	if (a < b)
		a = b;

	return a;
}

/*link https://codeforces.com/contest/990/problem/G */
/*input
3
1 2 3
1 2
2 3
*/
/*output
1 4
2 1
3 1
*/
/*input
6
1 2 4 8 16 32
1 6
6 3
3 4
4 2
6 5
*/
/*output
1 6
2 5
4 6
8 1
16 2
32 1
*/
/*input
4
9 16 144 6
1 3
2 3
4 3
*/
/*output
1 1
2 1
3 1
6 2
9 2
16 2
144 1
*/

ll gcd(ll a, ll b) {
	if (a > b)
		swap(a, b);

	if (a == 0)
		return b;

	return gcd(b % a, a);
}

vector<bool> apl;
vector<bool> apl2;
vector<int> gra[100000];
int n;
ll m;
vi ats;
vi dyd;
vi gyl;
vi a;
set<int> pask;
vi idom;
vi kiek;
const int lima = 200001;
int raskdyd(int d, int p) {
	apl2[d] = true;
	dyd[d] = 1;

	for (auto && i : gra[d]) {
		if (i == p or apl[i])
			continue;

		dyd[d] += raskdyd(i, d);
	}

	return dyd[d];
}
void raskgyl(int d, int p, ll dal = 0) {
	dal = gcd(a[d], dal);
	pask.insert(dal);
	kiek[dal]++;

	for (auto && i : gra[d]) {
		if (i == p or apl[i])
			continue;

		raskgyl(i, d, dal);
	}
}
int ieskok(int d, int p, int didz) {
	for (auto && i : gra[d]) {
		if (i == p or apl[i])
			continue;

		if (dyd[i] > didz)
			return ieskok(i, d, didz);
	}

	return d;
}
int main () {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n;
	a.resize(n);
	cin >> a;
	apl = vector<bool>(n, false);
	dyd = vi(n, 0);
	gyl = vi(n, 0);
	ats = vi(lima, 0);

	for (int i = 0; i < n - 1; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		gra[a].push_back(b);
		gra[b].push_back(a);
	}

	while (true) {
		bool rad = false;
		apl2 = vector<bool>(n, false);
		vi kiek2 = vi(200000, 0);
		kiek = vi(200000, 0);

		for (int i = 0; i < n; i++) {
			if (!apl[i] and !apl2[i]) {
				int dydis = raskdyd(i, -1);
				int cent = ieskok(i, -1, dydis / 2);

				ats[a[cent]]++;
				kiek2[a[cent]]++;
				set<int> idom;
				idom.insert(a[cent]);

				for (auto && j : gra[cent]) {
					if (apl[j])
						continue;

					pask.clear();
					raskgyl(j, cent, a[cent]);

					debug(pask, idom);

					for (auto && i : pask) {
						for (auto && j : idom) {
							ats[gcd(i, j)] += kiek2[j] * kiek[i];
						}
					}

					for (auto && i : pask) {
						idom.insert(i);
						kiek2[i] += kiek[i];
						kiek[i] = 0;
					}
				}

				for (auto && i : idom) {
					kiek2[i] = 0;
				}

				rad = true;
				apl[cent] = true;
			}
		}

		if (!rad)
			break;
	}

	for (int i = 1; i < lima; i++) {
		if (ats[i])
			cout << i << " " << ats[i] << "\n";
	}

}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax];
int a[nmax];
ll ans[nmax];
vi g[nmax];

vpii dfs(int i,int p = -1){
    vpii out;

    foa(j,d[a[i]]){
        out.pb({j,1});
    }

    foa(j,g[i]){
        if(j == p) continue;
        vpii noww = dfs(j,i);
        int pli,plj;
        pli = plj = 0;
        foa(jj,d[a[i]]){
            while(plj < noww.size() && noww[plj].F < jj) plj++;
            if(plj == noww.size() || noww[plj].F != jj) pli++,continue;
            ans[jj] += (ll)(out[pli].S-1)*noww[plj].S;
            out[pli].S += noww[plj].S;
            pli++;
        }
    }

    foa(j,out) ans[j.F] += j.S;

    return out;

}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j+=i) d[j].pb(i);
    }

    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0);

    fo_(i,nmax-1,0) for(int j = i*2; j < nmax;j += i) ans[i] -= ans[j];

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax];
int a[nmax];
ll ans[nmax];
map<int,ll> mp[nmax];
vi g[nmax];

map<int,ll> dfs(int i,int p = -1){
    map<int,ll> out;
    foa(j,d[a[i]]){
        out[j] = 1;
    }

    foa(j,g[i]){
        if(j == p) continue;
        map<int,ll> noww = dfs(j,i);
        foa(jj,d[a[i]]){
            ans[jj] += (out[jj]-1)*noww[jj];
        }
        foa(jj,d[a[i]]){
            out[jj] += noww[jj];
        }
    }

    foa(j,out) ans[j.F] += j.S;

    return out;

}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j+=i) d[j].pb(i);
    }

    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0);

    fo_(i,nmax-1,0) for(int j = i*2; j < nmax;j += i) ans[i] -= ans[j];

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax];
vi mp[nmax];
int a[nmax];
ll ans[nmax];
vi g[nmax];

void dfs(int i,int p = -1){

    foa(j,d[a[i]]){
        mp[i].pb(1);
    }

    foa(j,g[i]){
        if(j == p) continue;
        dfs(j,i);
        int pli,plj;
        pli = plj = 0;
        int sz = d[a[j]].size();
        foa(jj,d[a[i]]){
            while(plj < sz && d[a[j]][plj] < jj) plj++;
            if(plj == sz || d[a[j]][plj] != jj) {pli++; continue;}
            ans[jj] += (ll)(mp[i][pli]-1)*mp[j][plj];
            mp[i][pli] += mp[j][plj];
            pli++;
        }
    }

    fo(j,0,d[a[i]].size()) ans[d[a[i]][j]] += mp[i][j];
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j+=i) d[j].pb(i);
    }

    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0);

    fo_(i,nmax-1,0) for(int j = i*2; j < nmax;j += i) ans[i] -= ans[j];

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax],g[nmax];
vi now[nmax],kol;
int a[nmax];
int dnow;
bool seen[nmax];
ll ans[nmax];
ll ted;

void dfs(int i,int p){
    ted++;
    kol.pb(i);
    seen[i] = true;
    foa(j,g[i]){
        if(j == p || a[j]%dnow != 0) continue;
        dfs(j,i);
    }
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j += i) d[j].pb(i);
    }
    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n) foa(j,d[a[i]]) now[j].pb(i);
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }
    fo(i,1,nmax){
        dnow = i;
        foa(j,now[i]){
            if(seen[j]) continue;
            dfs(j,-1);
            ans[i] += ted*(ted+1)/2;
            ted = 0;
        }
        foa(i,kol) seen[i] = false;
        kol.clear();
    }

    fo_(i,nmax-1,0){
        for(int j = 2*i; j < nmax; j+=i) ans[i] -= ans[j];
    }
    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax],g[nmax];
map<int,ll> mp[nmax];
ll ans[nmax];
int a[nmax];

map<int,ll> dfs(int i,int p){
    map<int,ll> out;
    foa(j,g[i]){
        if(j==p) continue;
        map<int,ll> now = dfs(j,i);
        foa(jj,out) foa(kk,now) ans[__gcd(jj.F,kk.F)] += jj.S*kk.S;
        foa(kk,now) out[__gcd(a[i],kk.F)] += kk.S;
    }
    out[a[i]] += 1;
    foa(j,out) ans[j.F] += j.S;
    return out;
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j += i) d[j].pb(i);
    }
    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0,-1);

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax];
vpii mp[nmax];
int a[nmax];
ll ans[nmax];
vi g[nmax];

void dfs(int i,int p = -1){

    foa(j,d[a[i]]){
        mp[i].pb({j,1});
    }

    foa(j,g[i]){
        if(j == p) continue;
        dfs(j,i);
        int pli,plj;
        pli = plj = 0;
        int sz = mp[j].size();
        foa(jj,d[a[i]]){
            while(plj < sz && mp[j][plj].F < jj) plj++;
            if(plj == sz || mp[j][plj].F != jj) {pli++; continue;}
            ans[jj] += (ll)(mp[i][pli].S-1)*mp[j][plj].S;
            mp[i][pli].S += mp[j][plj].S;
            pli++;
        }
    }

    foa(j,mp[i]) ans[j.F] += j.S;
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j+=i) d[j].pb(i);
    }

    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0);

    fo_(i,nmax-1,0) for(int j = i*2; j < nmax;j += i) ans[i] -= ans[j];

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax];
int a[nmax];
ll ans[nmax];
vi g[nmax];

vpii dfs(int i,int p = -1){
    vpii out;

    foa(j,d[a[i]]){
        out.pb({j,1});
    }

    foa(j,g[i]){
        if(j == p) continue;
        vpii noww = dfs(j,i);
        int pli,plj;
        pli = plj = 0;
        foa(jj,d[a[i]]){
            while(plj < noww.size() && noww[plj].F < jj) plj++;
            if(plj == noww.size() || noww[plj].F != jj) {pli++; continue;}
            ans[jj] += (ll)(out[pli].S-1)*noww[plj].S;
            out[pli].S += noww[plj].S;
            pli++;
        }
    }

    foa(j,out) ans[j.F] += j.S;

    return out;

}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j+=i) d[j].pb(i);
    }

    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0);

    fo_(i,nmax-1,0) for(int j = i*2; j < nmax;j += i) ans[i] -= ans[j];

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax];
int a[nmax];
ll ans[nmax];
vi g[nmax];

vpll dfs(int i,int p = -1){
    vpll out;

    foa(j,d[a[i]]){
        out.pb({j,1});
    }

    foa(j,g[i]){
        if(j == p) continue;
        vpll noww = dfs(j,i);
        int pli,plj;
        pli = plj = 0;
        foa(jj,d[a[i]]){
            while(plj < noww.size() && noww[plj].F < jj) plj++;
            if(plj == noww.size() || noww[plj].F != jj) continue;
            ans[jj] += (out[pli].S-1)*noww[plj].S;
            pli++;
        }
        pli = plj = 0;
        foa(jj,d[a[i]]){
            while(plj < noww.size() && noww[plj].F < jj) plj++;
            if(plj == noww.size() || noww[plj].F != jj) continue;
            out[pli].S += noww[plj].S;
            pli++;
        }
    }

    foa(j,out) ans[j.F] += j.S;

    return out;

}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j+=i) d[j].pb(i);
    }

    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0);

    fo_(i,nmax-1,0) for(int j = i*2; j < nmax;j += i) ans[i] -= ans[j];

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax];
int a[nmax];
ll ans[nmax];
map<int,ll> mp[nmax];
vi g[nmax];

map<int,ll> dfs(int i,int p = -1){
    map<int,ll> out;
    foa(j,d[a[i]]){
        out[j] = 1;
    }

    foa(j,g[i]){
        if(j == p) continue;
        map<int,ll> noww = dfs(j,i);
        foa(jj,d[a[i]]){
            if(a[j]%jj == 0) ans[jj] += (out[jj]-1)*noww[jj];
        }
        foa(jj,d[a[i]]){
            if(a[j]%jj == 0) out[jj] += noww[jj];
        }
    }

    foa(j,out) ans[j.F] += j.S;

    return out;

}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j+=i) d[j].pb(i);
    }

    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0);

    fo_(i,nmax-1,0) for(int j = i*2; j < nmax;j += i) ans[i] -= ans[j];

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax];
int a[nmax];
ll ans[nmax];
map<int,ll> mp[nmax];
vi g[nmax];

void dfs(int i,int p = -1){
    foa(j,d[a[i]]){
        mp[i][j] = 1;
    }
    foa(j,g[i]){
        if(j == p) continue;
        dfs(j,i);
        foa(jj,d[a[i]]){
            mp[i][jj] += mp[j][jj];
        }
    }

    foa(j,mp[i]) ans[j.F] += j.S;

    map<int,ll> now;
    foa(j,g[i]){
        if(j == p) continue;
        foa(jj,d[a[i]]){
            ans[jj] += mp[j][jj]*now[jj];
        }
        foa(jj,d[a[i]]) now[jj] += mp[j][jj];
    }

}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j+=i) d[j].pb(i);
    }

    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0);

    fo_(i,nmax-1,0) for(int j = i*2; j < nmax;j += i) ans[i] -= ans[j];

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax];
int a[nmax];
ll ans[nmax];
vi g[nmax];

vpii dfs(int i,int p = -1){
    vpii out;
    bool done = false;

    foa(j,g[i]){
        if(j == p) continue;
        vpii noww = dfs(j,i);
        if(!done){
            foa(j,d[a[i]]) out.pb({j,1});
            done = true;
        }
        int pli,plj;
        pli = plj = 0;
        foa(jj,d[a[i]]){
            while(plj < noww.size() && noww[plj].F < jj) plj++;
            if(plj == noww.size() || noww[plj].F != jj) {pli++; continue;}
            ans[jj] += (ll)(out[pli].S-1)*noww[plj].S;
            out[pli].S += noww[plj].S;
            pli++;
        }
    }

    if(!done){
        foa(j,d[a[i]]) out.pb({j,1});
        done = true;
    }

    foa(j,out) ans[j.F] += j.S;

    return out;

}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j+=i) d[j].pb(i);
    }

    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0);

    fo_(i,nmax-1,0) for(int j = i*2; j < nmax;j += i) ans[i] -= ans[j];

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef double db;
typedef std::string str;
#define sei set<int>
#define sell set<ll>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define vvll vector<vll>
#define vld vector<ld>
#define vstr vector<str>
#define vpii vector<pii>
#define vpll vector<pll>
#define all(v) v.begin(),v.end()
#define foa(i,v) for(auto i : v)
#define fo(i,a,b) for(int i=a;i<b;i++)
#define fo_(i,a,b) for(int i=a;i>b;i--)
#define M(a) memset(a,0,sizeof a)
#define M_(a) memset(a ,-1,sizeof a)
#define deb(x)  cerr << #x << " = " << x << endl
#define pb push_back
#define pob pop_back
#define F first
#define S second
#define OK order_of_key
#define FO find_by_order
#define nmax 200100
const ld PI = 3.141592653589793238462643383279;
const ll inf = std::numeric_limits<ll>::max();
const int infint = std::numeric_limits<int>::max();
const ll mod = 1e9+7;
using namespace __gnu_pbds;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vi d[nmax],g[nmax];
map<int,ll> mp[nmax];
ll ans[nmax];
int a[nmax];

void dfs(int i,int p){
    foa(j,g[i]){
        if(j==p) continue;
        dfs(j,i);
        foa(jj,mp[i]) foa(kk,mp[j]) ans[__gcd(jj.F,kk.F)] += jj.S*kk.S;
        foa(kk,mp[j]) mp[i][__gcd(a[i],kk.F)] += kk.S;
    }
    mp[i][a[i]] += 1;
    foa(j,mp[i]) ans[j.F] += j.S;
}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);

    fo(i,1,nmax) d[i].pb(1);
    fo(i,2,nmax){
        for(int j = i; j < nmax; j += i) d[j].pb(i);
    }
    int n;
    cin >> n;
    fo(i,0,n) cin >> a[i];
    fo(i,0,n-1){
        int x,y;
        cin >> x >> y;
        x--,y--;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(0,-1);

    fo(i,1,nmax) if(ans[i]) cout << i << ' ' << ans[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define output              freopen("output.txt","w",stdout)
#define input               freopen("input.txt","r",stdin)
#define inputfile(x)        freopen(x,"r",stdin)
#define outputfile(x)       freopen(x,"w",stdout)
#define ensure(c,m)         assert(c && m)
///C IO
#define pf                  printf
#define sc                  scanf
#define pch                 putchar
#define ssc                 sscanf
#define spf                 sprintf

///functions
#define pb                  push_back
#define Mid(l,r)            ((l+r)>>1)
#define present(c,x)        ((c).find(x) != (c).end())
#define cpresent(c,x)       (find(all(c),x) != (c).end())
#define mp                  make_pair
#define xx                  first
#define yy                  second
#define endl                '\n'

#define forr(i,n)           for(int i=0;i<n;i++)
#define forr1(i,n)          for(int i=1;i<=n;i++)

///memory reset
#define MEM(Array,Val,Size) memset(Array,Val,(Size)*(sizeof(Array[0])))
#define SET(Array,Val)      memset(Array,Val,sizeof(Array))
#define set0(x)             memset(x,0,sizeof(x))
#define setn1(x)            memset(x,-1,sizeof(x))
#define setinf(x)           memset(x,127,sizeof(x))
///misc
#define SZ(v)               ((int) (v).size())
#define all(v)              (v).begin(), (v).end()
///bit operation single variable :: be careful with LL and ULL
#define On(x,i)             (x|=(1<<(i)))
#define Off(x,i)            (x&= ~(1<<(i)))
#define isOn(x,i)           (x&(1<<(i)))
#define Toggle(x,i)         (x^=(1<<(i)))
#define tmod(x,i)           (x&(~(-1<<i)))

template <class _T>inline void ina(_T a[],int n)        {forr(i,n)cin>>(a[i]);}

#define nln                 cout<<"\n"
#define sps cout<<" "
int TEST_CASE=0;
#define tcsp                cout<<"Case "<<(++TEST_CASE)<<": "
#define tcnl                cout<<"Case "<<(++TEST_CASE)<<":\n"
#define FAST                ios_base::sync_with_stdio(false);cin.tie(NULL);
#define precice(n)          cout<<setprecision(n)
#define FIX(n)              cout<<setprecision(n)<<fixed
//data type
typedef long long           ll;
typedef unsigned long long  ull;
typedef long double         LD;
typedef pair<int,int>       pii;
typedef pair<ll,ll>         pll;
typedef pair<double,double> pdd;
typedef vector<int>         vi;
// typedef __int128            LLL;
// typedef unsigned __int128   ULLL;
//BIG MOD / mod inverse
template<class _T>inline _T pow(_T a,_T b,_T m){a%=m;_T ans=1%m;while(b){if(b&1)ans*=a,ans%=m;a*=a;a%=m;b>>=1;}return ans;}
template<class _T>inline _T pow(_T a,_T b)      {_T ans=1;while(b){if(b&1)ans*=a;a*=a;b>>=1;}return ans;}
template<class _T>inline _T add(_T a,_T b,_T m){return a>=m-b?a-(m-b):a+b;}//a,b<m
template<class _T>inline _T multiply(_T a,_T b,_T m){_T ans=0;if(b>a)swap(a,b);while(b){if(b&1)ans=add(ans,a,m);b>>=1;a=add(a,a,m);}return ans;}//a,b<m
template<class _T>inline _T bigpow(_T a,_T b,_T m){a%=m;_T ans=1%m;while(b){if(b&1)ans=multiply(ans,a,m);a=multiply(a,a,m);b>>=1;}return ans;}
template<class _T>inline _T modinvers(_T a,_T m){return m>2000000000LL?bigpow(a,m-2,m):pow(a,m-2,m);}//m is prime
//egcd / mod inverse
template<class _T> _T _egcd(_T a, _T b, _T &x,_T &y){if(!b){x=1,y=0;return a;}_T _g=_egcd(b,a%b,x,y);_T xt=x;x=y,y=xt-(a/b)*y;return _g;}
template<class _T>inline _T fmodinvers(_T a,_T m){_T x,y;_egcd(a,m,x,y);x%=m;if(x<0)x+=m;return x;} //a,m co-prime
template<class _T>inline _T _lcm(_T a, _T b){return (a*b)/__gcd(a,b);}
template <class T> inline  T SQ(T a)            {return a*a;}
ll SQRT(ll n){ll e=sqrt(n*1.0);ll l=max(0LL,e-2),r=min(n,e+2);ll ans=0;while(l<=r){ll m=Mid(l,r);if(m*m<=n)ans=m,l=m+1;else r=m-1;}return ans;}
ll CBRT(ll n){ll e=cbrt(n*1.0);ll l=max(0LL,e-2),r=min(n,e+2);ll ans=0;while(l<=r){ll m=Mid(l,r);if(m*m*m<=n)ans=m,l=m+1;else r=m-1;}return ans;}
//direction array
/*
knight: int dx[]={1,-1,1,-1,2,2,-2,-2}; int dy[]={2,2,-2,-2,1,-1,1,-1};
Grid Side: int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};
*/
///constant
const LD EPS =              1e-9;
const LD PI=                acos(-1.0);
const int MX=             2e5+10;
ll mod=                     1e9+7;
unordered_map<int,int> table[MX];

int GCD(int i,int j)
{
	if( !i  || !j) return i?i:j;
	if(present(table[i], j)) return table[i][j];
	if(present(table[j], i)) return table[j][i];
	return table[i][j]=table[j][i]=GCD(j,i%j);

}

int sz[MX];
vi adj[MX];
bool del[MX];
int cals(int u,int p)
{
	sz[u]=1;
	for(int v: adj[u])
	{
		if(v!=p && !del[v])sz[u]+=cals(v,u);
	}
	return sz[u];
}

int cen(int u,int p,int s)
{
	for(int v: adj[u])
	{
		if(v!=p && !del[v] && sz[v]>=s/2)
			return cen(v,u,s);
	}
	return u;
}
int a[MX],cnt[MX]; ll ans[MX];
unordered_set<int> S;
void count(int u,int p,int g)
{
	g=GCD(g,a[u]);
	for(int e: S)
	{
		ans[ GCD(e,g)  ]+=cnt[e];
	}
	for(int v: adj[u])
		if(v!=p && !del[v])count(v,u,g);
}
void add(int u,int p,int g)
{
	g=GCD(g,a[u]);
	S.insert(g);
	cnt[g]++;
	for(int v: adj[u])
		if(v!=p && !del[ v ])add(v,u,g);
}

void sol(int u,int p)
{
	int s=cals(u,p);
	int c=cen(u,p,s);
	cnt[ a[c] ]=1;
	S.insert(a[c]);
	ans[a[c]]++;
	for(int v: adj[c])
	{
		if(!del[v])
		{
			count(v,c,0);
			add(v,c,a[c]);
		}
	}
	///clear cnt
	for(int i: S)cnt[i]=0;
	S.clear();
	del[c]=1;
	for(int v:adj[c])
		if(!del[v])
			sol(v,c);

}

int main()
{
	FAST
	int n,u,v;
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];

	for(int i=1;i<n;i++)
	{
		cin>>u>>v;
		adj[u].pb(v);
		adj[v].pb(u);
	}

	sol(1,0);

	for(int i=1;i<=200000;i++)
	{
		if(ans[i])
		{
			cout<<i<<" "<<ans[i]<<endl;
		}
	}
    return 0;
}

/**
Md. Tariqul Islam
IIT,JU
fb/tariqiitju
tarik.amtoly@gmail.com
*/


#include <bits/stdc++.h>
using namespace std;
#define output              freopen("output.txt","w",stdout)
#define input               freopen("input.txt","r",stdin)
#define inputfile(x)        freopen(x,"r",stdin)
#define outputfile(x)       freopen(x,"w",stdout)
#define ensure(c,m)         assert(c && m)
///C IO
#define pf                  printf
#define sc                  scanf
#define pch                 putchar
#define ssc                 sscanf
#define spf                 sprintf

///functions
#define pb                  push_back
#define Mid(l,r)            ((l+r)>>1)
#define present(c,x)        ((c).find(x) != (c).end())
#define cpresent(c,x)       (find(all(c),x) != (c).end())
#define mp                  make_pair
#define xx                  first
#define yy                  second
#define endl                '\n'

#define forr(i,n)           for(int i=0;i<n;i++)
#define forr1(i,n)          for(int i=1;i<=n;i++)

///memory reset
#define MEM(Array,Val,Size) memset(Array,Val,(Size)*(sizeof(Array[0])))
#define SET(Array,Val)      memset(Array,Val,sizeof(Array))
#define set0(x)             memset(x,0,sizeof(x))
#define setn1(x)            memset(x,-1,sizeof(x))
#define setinf(x)           memset(x,127,sizeof(x))
///misc
#define SZ(v)               ((int) (v).size())
#define all(v)              (v).begin(), (v).end()
///bit operation single variable :: be careful with LL and ULL
#define On(x,i)             (x|=(1<<(i)))
#define Off(x,i)            (x&= ~(1<<(i)))
#define isOn(x,i)           (x&(1<<(i)))
#define Toggle(x,i)         (x^=(1<<(i)))
#define tmod(x,i)           (x&(~(-1<<i)))

template <class _T>inline void ina(_T a[],int n)        {forr(i,n)cin>>(a[i]);}

#define nln                 cout<<"\n"
#define sps cout<<" "
int TEST_CASE=0;
#define tcsp                cout<<"Case "<<(++TEST_CASE)<<": "
#define tcnl                cout<<"Case "<<(++TEST_CASE)<<":\n"
#define FAST                ios_base::sync_with_stdio(false);cin.tie(NULL);
#define precice(n)          cout<<setprecision(n)
#define FIX(n)              cout<<setprecision(n)<<fixed
//data type
typedef long long           ll;
typedef unsigned long long  ull;
typedef long double         LD;
typedef pair<int,int>       pii;
typedef pair<ll,ll>         pll;
typedef pair<double,double> pdd;
typedef vector<int>         vi;
// typedef __int128            LLL;
// typedef unsigned __int128   ULLL;
//BIG MOD / mod inverse
template<class _T>inline _T pow(_T a,_T b,_T m){a%=m;_T ans=1%m;while(b){if(b&1)ans*=a,ans%=m;a*=a;a%=m;b>>=1;}return ans;}
template<class _T>inline _T pow(_T a,_T b)      {_T ans=1;while(b){if(b&1)ans*=a;a*=a;b>>=1;}return ans;}
template<class _T>inline _T add(_T a,_T b,_T m){return a>=m-b?a-(m-b):a+b;}//a,b<m
template<class _T>inline _T multiply(_T a,_T b,_T m){_T ans=0;if(b>a)swap(a,b);while(b){if(b&1)ans=add(ans,a,m);b>>=1;a=add(a,a,m);}return ans;}//a,b<m
template<class _T>inline _T bigpow(_T a,_T b,_T m){a%=m;_T ans=1%m;while(b){if(b&1)ans=multiply(ans,a,m);a=multiply(a,a,m);b>>=1;}return ans;}
template<class _T>inline _T modinvers(_T a,_T m){return m>2000000000LL?bigpow(a,m-2,m):pow(a,m-2,m);}//m is prime
//egcd / mod inverse
template<class _T> _T _egcd(_T a, _T b, _T &x,_T &y){if(!b){x=1,y=0;return a;}_T _g=_egcd(b,a%b,x,y);_T xt=x;x=y,y=xt-(a/b)*y;return _g;}
template<class _T>inline _T fmodinvers(_T a,_T m){_T x,y;_egcd(a,m,x,y);x%=m;if(x<0)x+=m;return x;} //a,m co-prime
template<class _T>inline _T _lcm(_T a, _T b){return (a*b)/__gcd(a,b);}
template <class T> inline  T SQ(T a)            {return a*a;}
ll SQRT(ll n){ll e=sqrt(n*1.0);ll l=max(0LL,e-2),r=min(n,e+2);ll ans=0;while(l<=r){ll m=Mid(l,r);if(m*m<=n)ans=m,l=m+1;else r=m-1;}return ans;}
ll CBRT(ll n){ll e=cbrt(n*1.0);ll l=max(0LL,e-2),r=min(n,e+2);ll ans=0;while(l<=r){ll m=Mid(l,r);if(m*m*m<=n)ans=m,l=m+1;else r=m-1;}return ans;}
//direction array
/*
knight: int dx[]={1,-1,1,-1,2,2,-2,-2}; int dy[]={2,2,-2,-2,1,-1,1,-1};
Grid Side: int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};
*/
///constant
const LD EPS =              1e-9;
const LD PI=                acos(-1.0);
const int MX=             2e5+10;
ll mod=                     1e9+7;
unordered_map<int,int> table[MX];

int GCD(int i,int j)
{
	if( !i  || !j) return i?i:j;
	if(present(table[i], j)) return table[i][j];
	if(present(table[j], i)) return table[j][i];
	int y=GCD(j,i%j);
	return table[i][j]=table[j][i]=y;

}

int sz[MX];
vi adj[MX];
bool del[MX];
int cals(int u,int p)
{
	sz[u]=1;
	for(int v: adj[u])
	{
		if(v!=p && !del[v])sz[u]+=cals(v,u);
	}
	return sz[u];
}

int cen(int u,int p,int s)
{
	for(int v: adj[u])
	{
		if(v!=p && !del[v] && sz[v]>=s/2)
			return cen(v,u,s);
	}
	return u;
}
int a[MX],cnt[MX]; ll ans[MX];
unordered_set<int> S;
void count(int u,int p,int g)
{
	g=GCD(g,a[u]);
	for(int e: S)
	{
		ans[ GCD(e,g)  ]+=cnt[e];
	}
	for(int v: adj[u])
		if(v!=p && !del[v])count(v,u,g);
}
void add(int u,int p,int g)
{
	g=GCD(g,a[u]);
	S.insert(g);
	cnt[g]++;
	for(int v: adj[u])
		if(v!=p && !del[ v ])add(v,u,g);
}

void sol(int u,int p)
{
	int s=cals(u,p);
	int c=cen(u,p,s);
	cnt[ a[c] ]=1;
	S.insert(a[c]);
	ans[a[c]]++;
	for(int v: adj[c])
	{
		if(!del[v])
		{
			count(v,c,0);
			add(v,c,a[c]);
		}
	}
	///clear cnt
	for(int i: S)cnt[i]=0;
	S.clear();
	del[c]=1;
	for(int v:adj[c])
		if(!del[v])
			sol(v,c);

}

int main()
{
	FAST
	int n,u,v;
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];

	for(int i=1;i<n;i++)
	{
		cin>>u>>v;
		adj[u].pb(v);
		adj[v].pb(u);
	}

	sol(1,0);

	for(int i=1;i<=200000;i++)
	{
		if(ans[i])
		{
			cout<<i<<" "<<ans[i]<<endl;
		}
	}
    return 0;
}

/**
Md. Tariqul Islam
IIT,JU
fb/tariqiitju
tarik.amtoly@gmail.com
*/


#include <bits/stdc++.h>
using namespace std;
#define output              freopen("output.txt","w",stdout)
#define input               freopen("input.txt","r",stdin)
#define inputfile(x)        freopen(x,"r",stdin)
#define outputfile(x)       freopen(x,"w",stdout)
#define ensure(c,m)         assert(c && m)
///C IO
#define pf                  printf
#define sc                  scanf
#define pch                 putchar
#define ssc                 sscanf
#define spf                 sprintf

///functions
#define pb                  push_back
#define Mid(l,r)            ((l+r)>>1)
#define present(c,x)        ((c).find(x) != (c).end())
#define cpresent(c,x)       (find(all(c),x) != (c).end())
#define mp                  make_pair
#define xx                  first
#define yy                  second
#define endl                '\n'

#define forr(i,n)           for(int i=0;i<n;i++)
#define forr1(i,n)          for(int i=1;i<=n;i++)

///memory reset
#define MEM(Array,Val,Size) memset(Array,Val,(Size)*(sizeof(Array[0])))
#define SET(Array,Val)      memset(Array,Val,sizeof(Array))
#define set0(x)             memset(x,0,sizeof(x))
#define setn1(x)            memset(x,-1,sizeof(x))
#define setinf(x)           memset(x,127,sizeof(x))
///misc
#define SZ(v)               ((int) (v).size())
#define all(v)              (v).begin(), (v).end()
///bit operation single variable :: be careful with LL and ULL
#define On(x,i)             (x|=(1<<(i)))
#define Off(x,i)            (x&= ~(1<<(i)))
#define isOn(x,i)           (x&(1<<(i)))
#define Toggle(x,i)         (x^=(1<<(i)))
#define tmod(x,i)           (x&(~(-1<<i)))

template <class _T>inline void ina(_T a[],int n)        {forr(i,n)cin>>(a[i]);}

#define nln                 cout<<"\n"
#define sps cout<<" "
int TEST_CASE=0;
#define tcsp                cout<<"Case "<<(++TEST_CASE)<<": "
#define tcnl                cout<<"Case "<<(++TEST_CASE)<<":\n"
#define FAST                ios_base::sync_with_stdio(false);cin.tie(NULL);
#define precice(n)          cout<<setprecision(n)
#define FIX(n)              cout<<setprecision(n)<<fixed
//data type
typedef long long           ll;
typedef unsigned long long  ull;
typedef long double         LD;
typedef pair<int,int>       pii;
typedef pair<ll,ll>         pll;
typedef pair<double,double> pdd;
typedef vector<int>         vi;
// typedef __int128            LLL;
// typedef unsigned __int128   ULLL;
//BIG MOD / mod inverse
template<class _T>inline _T pow(_T a,_T b,_T m){a%=m;_T ans=1%m;while(b){if(b&1)ans*=a,ans%=m;a*=a;a%=m;b>>=1;}return ans;}
template<class _T>inline _T pow(_T a,_T b)      {_T ans=1;while(b){if(b&1)ans*=a;a*=a;b>>=1;}return ans;}
template<class _T>inline _T add(_T a,_T b,_T m){return a>=m-b?a-(m-b):a+b;}//a,b<m
template<class _T>inline _T multiply(_T a,_T b,_T m){_T ans=0;if(b>a)swap(a,b);while(b){if(b&1)ans=add(ans,a,m);b>>=1;a=add(a,a,m);}return ans;}//a,b<m
template<class _T>inline _T bigpow(_T a,_T b,_T m){a%=m;_T ans=1%m;while(b){if(b&1)ans=multiply(ans,a,m);a=multiply(a,a,m);b>>=1;}return ans;}
template<class _T>inline _T modinvers(_T a,_T m){return m>2000000000LL?bigpow(a,m-2,m):pow(a,m-2,m);}//m is prime
//egcd / mod inverse
template<class _T> _T _egcd(_T a, _T b, _T &x,_T &y){if(!b){x=1,y=0;return a;}_T _g=_egcd(b,a%b,x,y);_T xt=x;x=y,y=xt-(a/b)*y;return _g;}
template<class _T>inline _T fmodinvers(_T a,_T m){_T x,y;_egcd(a,m,x,y);x%=m;if(x<0)x+=m;return x;} //a,m co-prime
template<class _T>inline _T _lcm(_T a, _T b){return (a*b)/__gcd(a,b);}
template <class T> inline  T SQ(T a)            {return a*a;}
ll SQRT(ll n){ll e=sqrt(n*1.0);ll l=max(0LL,e-2),r=min(n,e+2);ll ans=0;while(l<=r){ll m=Mid(l,r);if(m*m<=n)ans=m,l=m+1;else r=m-1;}return ans;}
ll CBRT(ll n){ll e=cbrt(n*1.0);ll l=max(0LL,e-2),r=min(n,e+2);ll ans=0;while(l<=r){ll m=Mid(l,r);if(m*m*m<=n)ans=m,l=m+1;else r=m-1;}return ans;}
//direction array
/*
knight: int dx[]={1,-1,1,-1,2,2,-2,-2}; int dy[]={2,2,-2,-2,1,-1,1,-1};
Grid Side: int dx[]={0,0,1,-1};int dy[]={1,-1,0,0};
*/
///constant
const LD EPS =              1e-9;
const LD PI=                acos(-1.0);
const int MX=             2e5+10;
ll mod=                     1e9+7;
unordered_map<int,int> table[MX];

int GCD(int i,int j)
{
	if( !i  || !j) return i?i:j;
	if(present(table[i], j)) return table[i][j];
	if(present(table[j], i)) return table[j][i];
	int y=GCD(j,i%j);
	return table[j][i]=y;

}

int sz[MX];
vi adj[MX];
bool del[MX];
int cals(int u,int p)
{
	sz[u]=1;
	for(int v: adj[u])
	{
		if(v!=p && !del[v])sz[u]+=cals(v,u);
	}
	return sz[u];
}

int cen(int u,int p,int s)
{
	for(int v: adj[u])
	{
		if(v!=p && !del[v] && sz[v]>=s/2)
			return cen(v,u,s);
	}
	return u;
}
int a[MX],cnt[MX]; ll ans[MX];
unordered_set<int> S;
void count(int u,int p,int g)
{
	g=GCD(g,a[u]);
	for(int e: S)
	{
		ans[ GCD(e,g)  ]+=cnt[e];
	}
	for(int v: adj[u])
		if(v!=p && !del[v])count(v,u,g);
}
void add(int u,int p,int g)
{
	g=GCD(g,a[u]);
	S.insert(g);
	cnt[g]++;
	for(int v: adj[u])
		if(v!=p && !del[ v ])add(v,u,g);
}

void sol(int u,int p)
{
	int s=cals(u,p);
	int c=cen(u,p,s);
	cnt[ a[c] ]=1;
	S.insert(a[c]);
	ans[a[c]]++;
	for(int v: adj[c])
	{
		if(!del[v])
		{
			count(v,c,0);
			add(v,c,a[c]);
		}
	}
	///clear cnt
	for(int i: S)cnt[i]=0;
	S.clear();
	del[c]=1;
	for(int v:adj[c])
		if(!del[v])
			sol(v,c);

}

int main()
{
	FAST
	int n,u,v;
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];

	for(int i=1;i<n;i++)
	{
		cin>>u>>v;
		adj[u].pb(v);
		adj[v].pb(u);
	}

	sol(1,0);

	for(int i=1;i<=200000;i++)
	{
		if(ans[i])
		{
			cout<<i<<" "<<ans[i]<<endl;
		}
	}
    return 0;
}

/**
Md. Tariqul Islam
IIT,JU
fb/tariqiitju
tarik.amtoly@gmail.com
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/priority_queue.hpp>
//#pragma GCC optimize("O3")
//#pragma GCC target("sse4")
//#pragma GCC target("avx2")

#define deb(x) cout << #x << " = " << x << "\n"
#define all(x) (x).begin(), (x).end()
#define len(x) (int) x.size()
#define lsb(x) (x) & -(x)
#define l(x) (x << 1) + 1
#define r(x) (x << 1) + 2

#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound

using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ld, ld> pld;
typedef pair <ll, ll> pll;

template <class T1, class T2 = less <T1>> using pb_heap = __gnu_pbds::priority_queue <T1, T2, binary_heap_tag>;
template <class T1, class T2 = null_type, class T3 = less <T1>> using pb_map = tree <T1, T2, T3, rb_tree_tag, tree_order_statistics_node_update>;
template <class T1, class T2 = null_type, class T3 = hash <T1>> using pb_umap = gp_hash_table <T1, T2, T3>;
template <class T1, class T2, class T3 = hash <T1>> using umap = unordered_map <T1, T2, T3>;
template <class T> using uset = unordered_set <T>;
template <class T> using vec = vector <T>;

const ll infll = numeric_limits <ll>::max() >> 1;
const int inf = numeric_limits <int>::max() >> 1;
const int N = 2e5 + 1;
int n;

ll cnt[N];
ll ans[N];

vec <int> divs[N];
vec <int> vert[N];

struct Graph {
    int par[N];
    int val[N];
    vec <int> adj[N];
} graph;

struct Dsu {
    int par[N];
    int cnt[N];
} dsu;

int root(int u) {
    if(dsu.par[u] == u) {
        return u;
    } else {
        return dsu.par[u] = root(dsu.par[u]);
    }
}

ll bin(ll x) {
    return x * (x + 1) >> 1;
}

ll unite(int u, int v) {
    u = root(u);
    v = root(v);
    if(dsu.cnt[u] < dsu.cnt[v]) {
        swap(u, v);
    }
    int cntu = dsu.cnt[u];
    int cntv = dsu.cnt[v];
    ll ret = bin(cntu + cntv) - bin(cntu) - bin(cntv);
    dsu.cnt[u] += cntv;
    dsu.par[v] = u;
    return ret;
}

void calc_divs() {
    for(int i = 1; i < N; ++i) {
        for(int j = i; j < N; j += i) {
            divs[j].pb(i);
        }
    }
}

void dfs(int u) {
    for(int v: graph.adj[u]) {
        if(v != graph.par[u]) {
            graph.par[v] = u;
            dfs(v);
        }
    }
}

void input() {
    cin >> n;
    for(int i = 1; i <= n; ++i) {
        cin >> graph.val[i];
    }
    for(int i = 1; i < n; ++i) {
        int u; cin >> u;
        int v; cin >> v;
        graph.adj[u].pb(v);
        graph.adj[v].pb(u);
    }
}

ll count(int d) {
    ll res = len(vert[d]);
    for(int e: vert[d]) {
        dsu.cnt[e] = 1;
        dsu.par[e] = e;
    }
    for(int e: vert[d]) {
        int p = graph.par[e];
        if(p && graph.val[p] % d == 0) {
            res += unite(e, p);
        }
    }
    return res;
}

void solve() {
    calc_divs();
    dfs(1);
    for(int i = 1; i <= n; ++i) {
        for(int e: divs[graph.val[i]]) {
            vert[e].pb(i);
        }
    }
    for(int i = 1; i < N; ++i) {
        cnt[i] = count(i);
    }
    for(int i = N - 1; i >= 1; --i) {
        ll res = cnt[i];
        for(int j = 2 * i; j < N; j += i) {
            res -= ans[j];
        }
        ans[i] = res;
    }
    for(int i = 1; i < N; ++i) {
        if(ans[i]) {
            cout << i << " " << ans[i] << "\n";
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    input();
    solve();
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/priority_queue.hpp>
//#pragma GCC optimize("O3")
//#pragma GCC target("sse4")
//#pragma GCC target("avx2")

#define deb(x) cout << #x << " = " << x << "\n"
#define all(x) (x).begin(), (x).end()
#define len(x) (int) x.size()
#define lsb(x) (x) & -(x)
#define l(x) (x << 1) + 1
#define r(x) (x << 1) + 2

#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound

using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ld, ld> pld;
typedef pair <ll, ll> pll;

template <class T1, class T2 = less <T1>> using pb_heap = __gnu_pbds::priority_queue <T1, T2, binary_heap_tag>;
template <class T1, class T2 = null_type, class T3 = less <T1>> using pb_map = tree <T1, T2, T3, rb_tree_tag, tree_order_statistics_node_update>;
template <class T1, class T2 = null_type, class T3 = hash <T1>> using pb_umap = gp_hash_table <T1, T2, T3>;
template <class T1, class T2, class T3 = hash <T1>> using umap = unordered_map <T1, T2, T3>;
template <class T> using uset = unordered_set <T>;
template <class T> using vec = vector <T>;

const ll infll = numeric_limits <ll>::max() >> 1;
const int inf = numeric_limits <int>::max() >> 1;
const int N = 2e5 + 1;
int n;

ll cnt[N];
ll ans[N];

vec <int> divs[N];
vec <int> vert[N];

struct Graph {
    int par[N];
    int val[N];
    vec <int> adj[N];
} graph;

struct Dsu {
    int par[N];
    int cnt[N];
} dsu;

int root(int u) {
    if(dsu.par[u] == u) {
        return u;
    } else {
        return dsu.par[u] = root(dsu.par[u]);
    }
}

ll bin(ll x) {
    return x * (x + 1) >> 1;
}

ll unite(int u, int v) {
    u = root(u);
    v = root(v);
    if(dsu.cnt[u] < dsu.cnt[v]) {
        swap(u, v);
    }
    int cntu = dsu.cnt[u];
    int cntv = dsu.cnt[v];
    ll ret = bin(cntu + cntv) - bin(cntu) - bin(cntv);
    dsu.cnt[u] += cntv;
    dsu.par[v] = u;
    return ret;
}

void calc_divs() {
    for(int i = 1; i < N; ++i) {
        for(int j = i; j < N; j += i) {
            divs[j].pb(i);
        }
    }
}

void dfs(int u) {
    for(int v: graph.adj[u]) {
        if(v != graph.par[u]) {
            graph.par[v] = u;
            dfs(v);
        }
    }
}

void input() {
    cin >> n;
    for(int i = 1; i <= n; ++i) {
        cin >> graph.val[i];
    }
    for(int i = 1; i < n; ++i) {
        int u; cin >> u;
        int v; cin >> v;
        graph.adj[u].pb(v);
        graph.adj[v].pb(u);
    }
}

int count(int d) {
    ll res = len(vert[d]);
    for(int e: vert[d]) {
        dsu.cnt[e] = 1;
        dsu.par[e] = e;
    }
    for(int e: vert[d]) {
        int p = graph.par[e];
        if(p && graph.val[p] % d == 0) {
            res += unite(e, p);
        }
    }
    return res;
}

void solve() {
    calc_divs();
    dfs(1);
    for(int i = 1; i <= n; ++i) {
        for(int e: divs[graph.val[i]]) {
            vert[e].pb(i);
        }
    }
    for(int i = 1; i < N; ++i) {
        cnt[i] = count(i);
    }
    for(int i = N - 1; i >= 1; --i) {
        ll res = cnt[i];
        for(int j = 2 * i; j < N; j += i) {
            res -= ans[j];
        }
        ans[i] = res;
    }
    for(int i = 1; i < N; ++i) {
        if(ans[i]) {
            cout << i << " " << ans[i] << "\n";
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    input();
    solve();
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/priority_queue.hpp>
//#pragma GCC optimize("O3")
//#pragma GCC target("sse4")
//#pragma GCC target("avx2")

#define deb(x) cout << #x << " = " << x << "\n"
#define all(x) (x).begin(), (x).end()
#define len(x) (ll) x.size()
#define lsb(x) (x) & -(x)
#define l(x) (x << 1) + 1
#define r(x) (x << 1) + 2

#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define lb lower_bound
#define ub upper_bound

using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef pair <ll, ll> pii;
typedef pair <ld, ld> pld;
typedef pair <ll, ll> pll;

template <class T1, class T2 = less <T1>> using pb_heap = __gnu_pbds::priority_queue <T1, T2, binary_heap_tag>;
template <class T1, class T2 = null_type, class T3 = less <T1>> using pb_map = tree <T1, T2, T3, rb_tree_tag, tree_order_statistics_node_update>;
template <class T1, class T2 = null_type, class T3 = hash <T1>> using pb_umap = gp_hash_table <T1, T2, T3>;
template <class T1, class T2, class T3 = hash <T1>> using umap = unordered_map <T1, T2, T3>;
template <class T> using uset = unordered_set <T>;
template <class T> using vec = vector <T>;

const ll infll = numeric_limits <ll>::max() >> 1;
const ll inf = numeric_limits <ll>::max() >> 1;
const ll N = 2e5 + 1;
ll n;

ll cnt[N];
ll ans[N];

vec <ll> divs[N];
vec <ll> vert[N];

struct Graph {
    ll par[N];
    ll val[N];
    vec <ll> adj[N];
} graph;

struct Dsu {
    ll par[N];
    ll cnt[N];
} dsu;

ll root(ll u) {
    if(dsu.par[u] == u) {
        return u;
    } else {
        return dsu.par[u] = root(dsu.par[u]);
    }
}

ll bin(ll x) {
    return x * (x + 1) >> 1;
}

ll unite(ll u, ll v) {
    u = root(u);
    v = root(v);
    if(dsu.cnt[u] < dsu.cnt[v]) {
        swap(u, v);
    }
    ll cntu = dsu.cnt[u];
    ll cntv = dsu.cnt[v];
    ll ret = bin(cntu + cntv) - bin(cntu) - bin(cntv);
    dsu.cnt[u] += cntv;
    dsu.par[v] = u;
    return ret;
}

void calc_divs() {
    for(ll i = 1; i < N; ++i) {
        for(ll j = i; j < N; j += i) {
            divs[j].pb(i);
        }
    }
}

void dfs(ll u) {
    for(ll v: graph.adj[u]) {
        if(v != graph.par[u]) {
            graph.par[v] = u;
            dfs(v);
        }
    }
}

void input() {
    cin >> n;
    for(ll i = 1; i <= n; ++i) {
        cin >> graph.val[i];
    }
    for(ll i = 1; i < n; ++i) {
        ll u; cin >> u;
        ll v; cin >> v;
        graph.adj[u].pb(v);
        graph.adj[v].pb(u);
    }
}

ll count(ll d) {
    ll res = len(vert[d]);
    for(ll e: vert[d]) {
        dsu.cnt[e] = 1;
        dsu.par[e] = e;
    }
    for(ll e: vert[d]) {
        ll p = graph.par[e];
        if(p && graph.val[p] % d == 0) {
            res += unite(e, p);
        }
    }
    return res;
}

void solve() {
    calc_divs();
    dfs(1);
    for(ll i = 1; i <= n; ++i) {
        for(ll e: divs[graph.val[i]]) {
            vert[e].pb(i);
        }
    }
    for(ll i = 1; i < N; ++i) {
        cnt[i] = count(i);
    }
    for(ll i = N - 1; i >= 1; --i) {
        ll res = cnt[i];
        for(ll j = 2 * i; j < N; j += i) {
            res -= ans[j];
        }
        ans[i] = res;
    }
    for(ll i = 1; i < N; ++i) {
        if(ans[i]) {
            cout << i << " " << ans[i] << "\n";
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    input();
    solve();
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/trie_policy.hpp>
#include <ext/rope>

#pragma 03

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define gcd __gcd
#define fastio ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define rep(i, n) for (int i=0; i<(n); i++)
#define rep1(i, n) for (int i=1; i<=(n); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define endl "\n"

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned uint;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;
typedef vector<bool> vb;
typedef vector<vector<bool>> vvb;
template<typename _def> using ordered_set=tree<_def, null_type, less<_def>, rb_tree_tag, tree_order_statistics_node_update>;
typedef trie<string, null_type, trie_string_access_traits<>, pat_trie_tag, trie_prefix_search_node_update> pref_trie;

struct custom_hashes {
    inline static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    template<typename T> //should take care of all types that can turn into integers
    size_t operator()(T x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64((uint64_t)x + FIXED_RANDOM);
    }
};

template<typename _F, typename _T> using safe_map=cc_hash_table<_F, _T, custom_hashes>;

constexpr int N=2e5+1;
safe_map<int, ll> m;
vector<pair<int, ll>> ans;
int n;
int a[N];
vi adj[N];
safe_map<int, ll> cnt[N];

//wow
//missed the simple trick of just considering all before (therefore reducing the need for double looping)
//probably x2 - x3 faster
//although I'm not sure AC

//complexity: O(n d^2 A[i])

void dfs(int u, int par=-1) {
    cnt[u][a[u]]++;
    m[a[u]]++;
    for(int v: adj[u]) if(v!=par) {
        dfs(v, u);
        for(const auto& l: cnt[v]) for(const auto& r: cnt[u]) m[gcd(l.fi, r.fi)]+=l.se*r.se;
        for(const auto& it: cnt[v]) cnt[u][gcd(it.fi, a[u])]+=it.se;
        cnt[v].clear();
    }
}

int32_t main() {
    fastio;
    cin>>n;
    rep(i, n) cin>>a[i];
    rep(i, n-1) {
        int u, v; cin>>u>>v;
        adj[--u].pb(--v);
        adj[v].pb(u);
    }
    dfs(0);
    for(const auto& it: m) ans.pb(it);
    sort(all(ans));
    for(auto& it: ans) cout<<it.fi<<' '<<it.se<<endl;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/trie_policy.hpp>
#include <ext/rope>

#pragma 03

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define gcd __gcd
#define fastio ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define rep(i, n) for (int i=0; i<(n); i++)
#define rep1(i, n) for (int i=1; i<=(n); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define endl "\n"

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned uint;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;
typedef vector<bool> vb;
typedef vector<vector<bool>> vvb;
template<typename _def> using ordered_set=tree<_def, null_type, less<_def>, rb_tree_tag, tree_order_statistics_node_update>;
typedef trie<string, null_type, trie_string_access_traits<>, pat_trie_tag, trie_prefix_search_node_update> pref_trie;

struct custom_hashes {
    inline static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    template<typename T> //should take care of all types that can turn into integers
    size_t operator()(T x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64((uint64_t)x + FIXED_RANDOM);
    }
};

template<typename _F, typename _T> using safe_map=cc_hash_table<_F, _T, custom_hashes>;

constexpr int N=2e5+1;
int n;
int a[N];
ll ans[N];
vi adj[N];
safe_map<int, ll> cnt[N];

//wow
//missed the simple trick of just considering all before (therefore reducing the need for double looping)
//probably x2 - x3 faster
//although I'm not sure AC

//complexity: O(n d^2 A[i])

void dfs(int u, int par=-1) {
    cnt[u][a[u]]++;
    ans[a[u]]++;
    for(int v: adj[u]) if(v!=par) {
        dfs(v, u);
        for(const auto& l: cnt[v]) for(const auto& r: cnt[u]) ans[gcd(l.fi, r.fi)]+=l.se*r.se;
        for(const auto& it: cnt[v]) cnt[u][gcd(it.fi, a[u])]+=it.se;
        cnt[v].clear();
    }
}

int32_t main() {
    fastio;
    cin>>n;
    rep(i, n) cin>>a[i];
    rep(i, n-1) {
        int u, v; cin>>u>>v;
        adj[--u].pb(--v);
        adj[v].pb(u);
    }
    dfs(rng()%n);
    rep(i, N) if(ans[i]) cout<<i<<' '<<ans[i]<<endl;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/trie_policy.hpp>
#include <ext/rope>

#pragma 03

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define gcd __gcd
#define fastio ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define rep(i, n) for (int i=0; i<(n); i++)
#define rep1(i, n) for (int i=1; i<=(n); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define endl "\n"

typedef long long ll;
typedef unsigned long long ull;
typedef unsigned uint;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;
typedef vector<bool> vb;
typedef vector<vector<bool>> vvb;
template<typename _def> using ordered_set=tree<_def, null_type, less<_def>, rb_tree_tag, tree_order_statistics_node_update>;
typedef trie<string, null_type, trie_string_access_traits<>, pat_trie_tag, trie_prefix_search_node_update> pref_trie;

struct custom_hashes {
    inline static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    template<typename T> //should take care of all types that can turn into integers
    size_t operator()(T x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64((uint64_t)x + FIXED_RANDOM);
    }
};

template<typename _F, typename _T> using safe_map=gp_hash_table<_F, _T, custom_hashes>;

constexpr int N=2e5+1;
safe_map<int, ll> m;
vector<pair<int, ll>> ans;
int n;
int a[N];
vi adj[N];
safe_map<int, ll> cnt[N];

void dfs(int u, int par=-1) {
    safe_map<int, ll> tmp;
    for(int v: adj[u]) if(v!=par) {
        dfs(v, u);
        for(const auto& it: cnt[v]) {
            cnt[u][gcd(it.fi, a[u])]+=it.se;
            m[gcd(it.fi, a[u])]+=it.se;
            tmp[it.fi]+=it.se;
        }
    }
    cnt[u][a[u]]++;
    m[a[u]]++;
    safe_map<int, ll> d;
    for(int v: adj[u]) if(v!=par) {
        for(const auto& it: cnt[v]) tmp[it.fi]-=it.se;
        for(const auto& l: cnt[v]) for(const auto& r: tmp) d[gcd(gcd(l.fi, r.fi), a[u])]+=l.se*r.se;
        for(const auto& it: cnt[v]) tmp[it.fi]+=it.se;
    }
    for(const auto& it: d) m[it.fi]+=it.se/2;
}

int32_t main() {
    fastio;
    cin>>n;
    rep(i, n) cin>>a[i];
    rep(i, n-1) {
        int u, v; cin>>u>>v;
        adj[--u].pb(--v);
        adj[v].pb(u);
    }
    dfs(0);
    for(const auto& it: m) ans.pb(it);
    sort(all(ans));
    for(auto& it: ans) cout<<it.fi<<' '<<it.se<<endl;
}


from sys import exit
n, k = [int(i) for i in input().split()]
if k % 2 == 0 or k >= 2 * n:
    print(-1)
    exit(0)
last = n
a = [0] * n
def ans(c, l, r):
    global last
    if c == 1:
        i = r - 1
        while i >= l:
            a[i] = last
            last -= 1
            i -= 1
        return
    m = (l + r) // 2
    ans(c // 2 - int((c // 2) % 2 == 0), l, m)
    ans(c // 2 + int((c // 2) % 2 == 0), m, r)
ans(k, 0, n)
print(*a)


import sys

n, k = map(int, input().split())
k = [k-1]
ans = [-1]*n

def set_n(l, r, rev, cur):
    if not rev:
        for i in range(l, r):
            ans[i] = cur
            cur += 1
    else:
        for i in range(r-1, l-1, -1):
            ans[i] = cur
            cur += 1

    return cur

def rec(l, r, cur):
    # print(l, r, k, ans)
    if r - l == 1:
        set_n(l, r, 0, cur)
        return

    if k[0] < 2:
        set_n(l, r, 0, cur)
        return

    k[0] -= 2
    mid = (l + r) >> 1
    rec(mid, r, cur)
    rec(l, mid, cur+(r - mid))

rec(0, n, 1)
if k[0] != 0:
    print(-1)
else:
    print(*ans)


import sys

n, k = map(int, input().split())
k = [k-1]
ans = [-1]*n
cur = n

def set_n(l, r, rev):
    global cur
    if not rev:
        for i in range(r-1, l-1, -1):
            ans[i] = cur
            cur -= 1
    else:
        for i in range(l, r):
            ans[i] = cur
            cur -= 1

def rec(l, r):
    # print(l, r, k, ans)
    if r - l == 1:
        set_n(l, r, 0)
        return

    if r - l == 2:
        if k[0] & 1:
            set_n(l, r, 1)
            k[0] -= 1
        else:
            set_n(l, r, 0)
        return

    if k[0] < 2:
        set_n(l, r, 0)
        return

    k[0] -= 2
    mid = (l + r) >> 1
    set_n(mid, mid+1, 0)
    rec(l, mid)
    rec(mid+1, r)

rec(0, n)
if k[0] != 0:
    print(-1)
else:
    print(*ans)


n, k = map(int, input().split())

lst = [i for i in range(1, n + 1)]

def rearrange(l, r):
    global k
    if k < 1 or l + 1 == r:
        return
    k -= 2
    mid = (l + r) // 2
    lst[mid - 1], lst[mid] = lst[mid], lst[mid - 1]
    rearrange(l, mid)
    rearrange(mid, r)

if k % 2 == 0 or n * 2 < k:
    print(-1)
else:
    k -= 1
    rearrange(0, n)
    print(' '.join(str(i) for i in lst))


#Bhargey Mehta (Sophomore)
#DA-IICT, Gandhinagar
import sys, math, queue, bisect
#sys.stdin = open("input.txt", "r")
MOD = 10**9+7
sys.setrecursionlimit(1000000)

n, k = map(int, input().split())
a = [-1 for i in range(n)]
c = 1

def merge(l, r, k):
    global c, a
    if l == r:
        return False
    k -= 1
    if k == 0:
        for i in range(l, r):
            a[i] = c
            c += 1
        return True
    if k == 1:
        return False
    m = l+(r-l)//2
    if (k//2)%2 == 1:
        if merge(m, r, k//2):
            return merge(l, m, k//2)
    else:
        if merge(m, r, k//2+1):
            return merge(l, m, k//2-1)
    return False

if not merge(0, n, k):
    print(-1)
    exit()
print(*a)


#Bhargey Mehta (Sophomore)
#DA-IICT, Gandhinagar
import sys, math, queue, bisect
#sys.stdin = open("input.txt", "r")
MOD = 10**9+7
sys.setrecursionlimit(1000000)

n, k = map(int, input().split())
a = [-1 for i in range(n)]
c = 1

def merge(l, r, k):
    global c, a
    if l >= r:
        return False
    k -= 1
    if k == 0:
        for i in range(l, r):
            a[i] = c
            c += 1
        return True
    if k%2 == 1:
        return False
    m = l+(r-l)//2
    if (k//2)%2 == 1:
        if merge(m, r, k//2):
            return merge(l, m, k//2)
    else:
        if merge(m, r, k//2+1):
            return merge(l, m, k//2-1)
    return False

if not merge(0, n, k):
    print(-1)
    exit()
print(*a)


#Bhargey Mehta (Sophomore)
#DA-IICT, Gandhinagar
import sys, math, queue, bisect
#sys.stdin = open("input.txt", "r")
MOD = 10**9+7
sys.setrecursionlimit(1000000)

n, k = map(int, input().split())
a = [-1 for i in range(n)]
c = 1

def merge(l, r, k):
    global c, a
    if l == r:
        return False
    k -= 1
    if k == 0:
        for i in range(l, r):
            a[i] = c
            c += 1
        return True
    if k == 1:
        return False
    m = l+(r-l)//2
    stat = True
    stat = stat and merge(m, r, k-k//2)
    stat = stat and merge(l, m, k//2)
    for i in range(l, m):
        t = a[i]
        a[i] = a[m-1-i]
        a[m-1-i] = t
    for i in range(m, r):
        t = a[i]
        a[i] = a[r-1-i]
        a[r-1-i] = t
    return stat
if not merge(0, n, k):
    print(-1)
    exit()
print(*a)


#Bhargey Mehta (Sophomore)
#DA-IICT, Gandhinagar
import sys, math, queue, bisect
#sys.stdin = open("input.txt", "r")
MOD = 10**9+7
sys.setrecursionlimit(1000000)

n, k = map(int, input().split())
a = [-1 for i in range(n)]

def merge(l, r, k):
    if l == r:
        return False
    k -= 1
    if k == 0:
        for i in range(l, r):
            a[i] = i+1
        return True
    if k == 1:
        return False
    m = (l+r)//2
    stat = True
    stat = stat and merge(l, m, k//2)
    stat = stat and merge(m, r, k-k//2)
    for i in range(l, m):
        t = a[i]
        a[i] = a[m-1-i]
        a[m-1-i] = t
    for i in range(m, r):
        t = a[i]
        a[i] = a[r-1-i]
        a[r-1-i] = t
    return stat
if not merge(0, n, k):
    print(-1)
    exit()
print(*a)


#Bhargey Mehta (Sophomore)
#DA-IICT, Gandhinagar
import sys, math, queue, bisect
#sys.stdin = open("input.txt", "r")
MOD = 10**9+7
sys.setrecursionlimit(1000000)

n, k = map(int, input().split())
k -= 1
a = [-1 for i in range(n)]
c = 1

def merge(l, r, k):
    global a, c
    if l >= r or k%2 != 0:
        return False
    if k == 0:
        for i in range(l, r):
            a[i] = c
            c += 1
        return True
    k -= 2
    m = (l+r)//2
    if (k//2)%2 == 0:
        if merge(m, r, k//2):
            return merge(l, m, k//2)
        else:
            return False
    else:
        if merge(m, r, k//2+1):
            return merge(l, m, k//2-1)
        else:
            return False
if not merge(0, n, k):
    print(-1)
    exit()
print(*a)


n,k = [int(x) for x in input().split()]

if k%2 == 0:
    print(-1)
else:
    # a completely unsorted list of length n
    # will have 2(n-1) child calls

    if k > 2*n-1:
        print(-1)
    else:
        arr = [n-x for x in range(n)]

        sorts = 2*n-1-k

        segs = [[(0,n,n//2)]]

        layers = 0
        nCopy = n

        while nCopy:
            layers += 1
            nCopy //= 2

        for x in range(layers):
            newSeg = []
            for l,r,mid in segs[x]:
                if mid-l > 1:
                    newSeg.append((l,mid,(mid+l)//2))
                if r-mid > 1:
                    newSeg.append((mid,r,(mid+r)//2))
            segs.append(newSeg)
        for x in range(sorts//2):
            while not segs[-1]:
                segs.pop()
            l,r,mid = segs[-1].pop()
            newPart = arr[mid:r] + arr[l:mid]
            arr[l:r] = newPart
        print(' '.join([str(x) for x in arr]))


from sys import stdin, stdout

n, k = map(int, stdin.readline().split())
value = n
cnt = k
ans = []

def generate(l, r):
    global cnt, value
    cnt -= 1

    if l == r:
        ans.append(value)
        value -= 1
        return 0

    if not cnt:
        for i in range(value - (r - l), value + 1):
            ans.append(i)

        value -= (r - l + 1)
        return 0

    middle = (l + r + 1) >> 1
    generate(l, middle - 1)

    if not cnt:
        for i in range(1, value + 1):
            ans.append(i)
            return 0

    generate(middle, r)

generate(0, n - 1)
if len(ans) != n or cnt:
    stdout.write('-1')
else:
    stdout.write(' '.join(list(map(str, ans))))


from sys import stdin, stdout

n, k = map(int, stdin.readline().split())
value = n
cnt = k
ans = []

def generate(l, r):
    global cnt, value

    if l == r:
        ans.append(value)
        value -= 1
        return 0

    if not cnt:
        for i in range(value - (r - l), value + 1):
            ans.append(i)

        value -= (r - l + 1)
        return 0

    cnt -= 2
    middle = (l + r + 1) >> 1
    generate(l, middle - 1)
    generate(middle, r)

cnt -= 1
generate(0, n - 1)

if len(ans) != n or cnt:
    stdout.write('-1')
else:
    stdout.write(' '.join(list(map(str, ans))))


from sys import stdin, stdout

n, k = map(int, stdin.readline().split())
value = n
cnt = k
ans = []

def generate(l, r):
    global cnt, value
    cnt -= 1

    if l == r:
        ans.append(value)
        value -= 1
        return 0

    if not cnt:
        for i in range(value - (r - l), value + 1):
            ans.append(i)

        value -= (r - l + 1)
        return 0

    middle = (l + r + 1) >> 1
    generate(l, middle - 1)

    if not cnt:
        for i in range(1, value + 1):
            ans.append(i)
            return 0

    generate(middle, r)

generate(0, n - 1)
if len(ans) != n:
    stdout.write('-1')
else:
    stdout.write(' '.join(list(map(str, ans))))


n, k = map(int, input().split())

if k >= n:
    print("-1")
elif k == 1:
    print(*list(range(1, n+1)))
else:
    l = list(range(1, n+1))
    print(*(sorted(l[:k-1], reverse = True)+l[k-1:]))


n, k = map(int, input().split())

if k > n:
    print("-1")
elif k == 1:
    print(*list(range(1, n+1)))
else:
    l = list(range(1, n+1))
    print(*(sorted(l[:k-1], reverse = True)+l[k-1:]))


from sys import setrecursionlimit as c
c(10000)

def s(a, le, ri):
    global k
    if k <= 0 or le >= ri-1:
        return
    k -= 2
    mid = (le+ri)//2
    a[mid], a[mid-1] = a[mid-1], a[mid]
    s(a, le, mid)
    s(a, mid, ri)

n, k = map(int, input().split())

if not(k%2):
    print("-1")
else:
    k -= 1
    l = list(range(1, n+1))
    s(l, 0, n)
    if not(k):
        print(*l)
    else:
        print("-1")


# your code goes here
# your code goes here
size, call_no = map(int, input().split())

list_val = [i for i in range(1,size+1)]

#print(list_val)

def modify(list_val,l,r):
	global count

	if count == call_no or r==l:
		return
	mid = (l+r)//2
	temp = list_val[mid]
	list_val[mid] = list_val[mid-1]
	list_val[mid-1] = temp
	count+=2
	modify(list_val,l,mid-1)
	modify(list_val,mid,r)

if call_no == 1:
	str_val = " ".join(str(x) for x in list_val)
	print(str_val)

elif call_no%2 == 0:
	print("-1")

else:
    count = 1
    modify(list_val,0,len(list_val)-1)
    if count < call_no:
        print("-1")
    else:
        print(" ".join(str(x) for x in list_val))


# your code goes here
size, call_no = map(int, input().split())

list_val = [i for i in range(1,size+1)]

#print(list_val)

def modify(list_val,l,r):
	global count

	if count == call_no or r-l<2:
		return
	mid = (l+r)//2
	temp = list_val[mid]
	list_val[mid] = list_val[mid-1]
	list_val[mid-1] = temp
	count+=2
	modify(list_val,l,mid)
	modify(list_val,mid,r)

if call_no == 1:
	str_val = " ".join(str(x) for x in list_val)
	print(str_val)

elif call_no%2 == 0:
	print("-1")

else:
    count = 1
    modify(list_val,0,len(list_val))
    if count < call_no:
        print("-1")
    else:
        print(" ".join(str(x) for x in list_val))


# your code goes here
# your code goes here
size, call_no = map(int, input().split())

list_val = [i for i in range(1,size+1)]

#print(list_val)

def modify(list_val,l,r):
	global count

	if count == call_no or r==l:
		return
	mid = (l+r)//2
	temp = list_val[mid+1]
	list_val[mid+1] = list_val[mid]
	list_val[mid] = temp
	count+=2
	modify(list_val,l,mid)
	modify(list_val,mid+1,r)

if call_no == 1:
	str_val = " ".join(str(x) for x in list_val)
	print(str_val)

elif call_no%2 == 0:
	print("-1")

else:
    count = 1
    modify(list_val,0,len(list_val)-1)
    if count < call_no:
        print("-1")
    else:
        print(" ".join(str(x) for x in list_val))