#include <bits/stdc++.h>
using namespace std;
int sz[100005];
int at[100005];
int pos[100005];
bitset<1001> tree[4 * 100005];
bitset<1001> primes;
bitset<1001> res;
int lazy[4 * 100005];
int H;
int n, m;
int a[100005];
unordered_map<int, list<int>> g;
void dfs(int u, int p) {
  sz[u] = 1;
  at[++H] = u;
  pos[u] = H;
  for (int v : g[u]) {
    if (v == p) continue;
    dfs(v, u);
    sz[u] += sz[v];
  }
}
void build(int idx, int l, int r) {
  if (l == r) {
    tree[idx].set(a[at[l]]);
    return;
  }
  int mid = (l + r) / 2;
  build(2 * idx, l, mid);
  build(2 * idx + 1, mid + 1, r);
  tree[idx] = (tree[2 * idx] | tree[2 * idx + 1]);
}
void update(int idx, int ql, int qr, int l, int r, int v) {
  if (lazy[idx] != 0) {
    if (lazy[idx] >= m) lazy[idx] -= m;
    tree[idx] = (tree[idx] << lazy[idx] | tree[idx] >> (m - lazy[idx]));
    if (l != r) {
      lazy[2 * idx] += lazy[idx];
      lazy[2 * idx + 1] += lazy[idx];
      if (lazy[2 * idx] >= m) lazy[2 * idx] -= m;
      if (lazy[2 * idx + 1] >= m) lazy[2 * idx + 1] -= m;
    }
    lazy[idx] = 0;
  }
  if (l > qr || r < ql || l > r) return;
  if (ql <= l && r <= qr) {
    tree[idx] = (tree[idx] << v | tree[idx] >> (m - v));
    if (l != r) {
      lazy[2 * idx] += v;
      lazy[2 * idx + 1] += v;
      if (lazy[2 * idx] >= m) lazy[2 * idx] -= m;
      if (lazy[2 * idx + 1] >= m) lazy[2 * idx + 1] -= m;
    }
    return;
  }
  int mid = (l + r) / 2;
  update(2 * idx, ql, qr, l, mid, v);
  update(2 * idx + 1, ql, qr, mid + 1, r, v);
  tree[idx] = (tree[2 * idx] | tree[2 * idx + 1]);
}
void query(int idx, int ql, int qr, int l, int r) {
  if (l > qr || r < ql || l > r) return;
  if (lazy[idx] != 0) {
    if (lazy[idx] >= m) lazy[idx] -= m;
    tree[idx] = (tree[idx] << lazy[idx] | tree[idx] >> (m - lazy[idx]));
    if (l != r) {
      lazy[2 * idx] += lazy[idx];
      lazy[2 * idx + 1] += lazy[idx];
      if (lazy[2 * idx] >= m) lazy[2 * idx] -= m;
      if (lazy[2 * idx + 1] >= m) lazy[2 * idx + 1] -= m;
    }
    lazy[idx] = 0;
  }
  if (ql <= l && r <= qr) {
    res |= tree[idx];
    return;
  }
  int mid = (l + r) / 2;
  query(2 * idx, ql, qr, l, mid);
  query(2 * idx + 1, ql, qr, mid + 1, r);
}
int main() {
  H = 0;
  cin >> n >> m;
  for (int i = 2; i < m; i++) {
    bool p = true;
    for (int j = 2; j < i; j++) {
      if (i % j == 0) p = false;
    }
    if (p) primes.set(i);
  }
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
    a[i] %= m;
  }
  for (int i = 0; i < n - 1; i++) {
    int x, y;
    cin >> x >> y;
    g[x].push_back(y);
    g[y].push_back(x);
  }
  dfs(1, 0);
  build(1, 1, n);
  int q;
  cin >> q;
  for (int i = 0; i < q; i++) {
    int t, v, x;
    cin >> t >> v;
    if (t == 1) {
      cin >> x;
      x = x % m;
      update(1, pos[v], pos[v] + sz[v] - 1, 1, n, x);
    } else {
      res.reset();
      query(1, pos[v], pos[v] + sz[v] - 1, 1, n);
      res = res & primes;
      cout << res.count() << endl;
    }
  }
  return 0;
}
