#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXC = 10000000;
int N, Q;
vector<int> cval;
vector<vector<int>> g;
vector<int> euler;
vector<int> inT, outT;
int timerT = 0;
int LOGN = 17;
vector<vector<int>> up;
vector<int> depthv;
void dfs(int u, int p){
up[u][0] = p<0?u:p;
for(int k=1;k<LOGN;k++) up[u][k] = up[ up[u][k-1] ][k-1];
inT[u] = timerT;
euler[timerT++] = u;
for(int v: g[u]) if(v!=p){
depthv[v]=depthv[u]+1;
dfs(v,u);
}
outT[u] = timerT;
euler[timerT++] = u;
}
int lca(int a, int b){
if(depthv[a]<depthv[b]) swap(a,b);
int diff = depthv[a]-depthv[b];
for(int k=0;k<LOGN;k++) if(diff&(1<<k)) a = up[a][k];
if(a==b) return a;
for(int k=LOGN-1;k>=0;k--) if(up[a][k]!=up[b][k]){ a=up[a][k]; b=up[b][k]; }
return up[a][0];
}
inline long long hilbertOrder(int x, int y, int pow, int rot) {
if (pow == 0) return 0;
int hpow = 1 << (pow-1);
int seg = ( (x < hpow) ? ( (y < hpow) ? 0 : 3 ) : ( (y < hpow) ? 1 : 2 ) );
seg = (seg + rot) & 3;
static const int rotateDelta[4] = {3, 0, 0, 1};
int nx = x & (hpow-1), ny = y & (hpow-1);
int nrot = (rot + rotateDelta[seg]) & 3;
long long subSquareSize = 1LL << (2*pow - 2);
long long ord = seg * subSquareSize;
long long add = hilbertOrder(nx, ny, pow-1, nrot);
ord += (seg == 1 || seg == 2) ? add : (subSquareSize - add - 1);
return ord;
}
struct Query{
int l, r, lca, id;
long long ord;
bool operator<(Query const& o) const{
return ord < o.ord;
}
};
static int *spf_ptr = nullptr;
static signed char *mu_ptr = nullptr;
void linear_sieve_and_mobius(int maxv){
int n = maxv;
int *spf = new int[n+1];
signed char *mu = new signed char[n+1];
vector<int> primes;
mu[0] = 0; mu[1] = 1; spf[0]=0; spf[1]=1;
for(int i=2;i<=n;i++) spf[i]=0;
for(int i=2;i<=n;i++){
if(!spf[i]){ spf[i]=i; primes.push_back(i); mu[i] = -1; }
for(int p: primes){
ll v = 1LL*p*i; if(v>n) break;
spf[v] = p;
if(i % p == 0){ mu[v] = 0; break; }
else mu[v] = -mu[i];
}
}
spf_ptr = spf;
mu_ptr = mu;
}
inline int spf(int x){ return spf_ptr[x]; }
inline signed char mu(int x){ return mu_ptr[x]; }
vector<vector<int>> sqfree_divs;
void gen_sqfree_divs_for_all(){
sqfree_divs.assign(N, {});
for(int i=0;i<N;i++){
int x = cval[i];
vector<int> primes;
while(x>1){
int p = spf(x);
primes.push_back(p);
while(x%p==0) x/=p;
}
int m = primes.size();
int subsets = 1<<m;
sqfree_divs[i].reserve(subsets);
for(int mask=1; mask<subsets; ++mask){
ll prod = 1;
for(int j=0;j<m;j++) if(mask&(1<<j)) prod *= primes[j];
if(prod <= MAXC) sqfree_divs[i].push_back((int)prod);
}
sqfree_divs[i].push_back(1);
}
}
static int *cntDiv = nullptr;
vector<char> active;
ll currentPairs = 0;
int activeCount = 0;
inline void add_node(int node){
if(!active[node]){
ll cop = 0;
for(int d: sqfree_divs[node]){
cop += (ll) mu(d) * (ll) cntDiv[d];
}
currentPairs += cop;
for(int d: sqfree_divs[node]) cntDiv[d]++;
active[node]=1;
activeCount++;
} else {
for(int d: sqfree_divs[node]) cntDiv[d]--;
ll cop = 0;
for(int d: sqfree_divs[node]){
cop += (ll) mu(d) * (ll) cntDiv[d];
}
currentPairs -= cop;
active[node]=0;
activeCount--;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> N >> Q;
cval.assign(N,0);
int maxc = 1;
for(int i=0;i<N;i++){ cin >> cval[i]; maxc = max(maxc, cval[i]); }
g.assign(N,{});
for(int i=0;i<N-1;i++){ int u,v; cin>>u>>v; --u;--v; g[u].push_back(v); g[v].push_back(u); }
linear_sieve_and_mobius(maxc);
inT.assign(N,0); outT.assign(N,0);
euler.assign(2*N, -1);
timerT=0;
LOGN = 1;
while((1<<LOGN) <= N) LOGN++;
up.assign(N, vector<int>(LOGN));
depthv.assign(N,0);
dfs(0,-1);
gen_sqfree_divs_for_all();
cntDiv = (int*)calloc((maxc+1), sizeof(int));
vector<Query> queries; queries.reserve(Q);
int H = 0;
while((1<<H) < 2*N) H++;
for(int i=0;i<Q;i++){
int u,v; cin>>u>>v; --u; --v;
if(inT[u] > inT[v]) swap(u,v);
int w = lca(u,v);
Query qu;
qu.id = i;
if(w==u){
qu.l = inT[u]; qu.r = inT[v]; qu.lca = -1;
} else {
qu.l = outT[u]; qu.r = inT[v]; qu.lca = w;
}
qu.ord = hilbertOrder(qu.l, qu.r, H, 0);
queries.push_back(qu);
}
sort(queries.begin(), queries.end());
vector<ll> ans(Q);
active.assign(N,0);
currentPairs = 0; activeCount = 0;
int L = 0, R = -1;
for(auto &q: queries){
while(L > q.l) add_node(euler[--L]);
while(R < q.r) add_node(euler[++R]);
while(L < q.l) add_node(euler[L++]);
while(R > q.r) add_node(euler[R--]);
if(q.lca != -1){
add_node(q.lca);
ans[q.id] = currentPairs;
add_node(q.lca);
} else {
ans[q.id] = currentPairs;
}
}
for(int i=0;i<Q;i++) cout << ans[i] << '\n';
return 0;
}