#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline void next_int(T &x) {
  x = 0;
  char c;
  bool neg = false;
  while (!isdigit(c = getchar()))
    if (c == '-') neg = true;
  do x = x * 10 + c - 48;
  while (isdigit(c = getchar()));
  if (neg) x = -x;
}
template <typename T>
inline void write_int(T x, char last = 0) {
  if (x < 0) putchar('-'), x = abs(x);
  char tmp[20];
  int cnt = 0;
  while (x >= 10) tmp[cnt++] = x % 10 + 48, x /= 10;
  tmp[cnt] = x + 48;
  for (int i = (cnt); i >= (0); --i) putchar(tmp[i]);
  if (last) putchar(last);
}
const int N = (int)1e5 + 5;
int n, m, timer, tin[N], tout[N], a[N], aa[N], lazy[1 << 18];
bitset<1000> p, tree[1 << 18], emp;
vector<int> g[N];
void dfs_prep(int u, int p) {
  tin[u] = ++timer, aa[timer] = a[u];
  for (int i = (0); i < (((int)g[u].size())); ++i) {
    int v = g[u][i];
    if (v == p) continue;
    dfs_prep(v, u);
  }
  tout[u] = timer;
}
void init() {
  dfs_prep(1, 0);
  for (int i = (2); i < (m); ++i) p[i] = 1;
  for (int i = (2); i < (m); ++i)
    if (p[i]) {
      for (int j = i + i; j < m; j += i) p[j] = 0;
    }
}
void build_tree(int k, int l, int r) {
  if (l > r) return;
  if (l == r) {
    tree[k][aa[l] % m] = 1;
    return;
  }
  int mid = (l + r) >> 1;
  build_tree(k << 1, l, mid);
  build_tree(k << 1 | 1, mid + 1, r);
  tree[k] = (tree[k << 1] | tree[k << 1 | 1]);
}
inline void lazy_update(int k, int l, int r) {
  if (!lazy[k]) return;
  int val = lazy[k];
  lazy[k] = 0;
  tree[k] = ((tree[k] >> (m - val)) | (tree[k] << val));
  if (l != r) {
    lazy[k << 1] = (lazy[k << 1] + val) % m;
    lazy[k << 1 | 1] = (lazy[k << 1 | 1] + val) % m;
  }
}
void update(int k, int l, int r, int L, int R, int val) {
  lazy_update(k, l, r);
  if (l > r || l > R || r < L) return;
  if (L <= l && r <= R) {
    lazy[k] = (lazy[k] + val) % m;
    lazy_update(k, l, r);
    return;
  }
  int mid = (l + r) >> 1;
  update(k << 1, l, mid, L, R, val);
  update(k << 1 | 1, mid + 1, r, L, R, val);
  tree[k] = (tree[k << 1] | tree[k << 1 | 1]);
}
bitset<1000> query(int k, int l, int r, int L, int R) {
  if (l > r || l > R || r < L) return emp;
  lazy_update(k, l, r);
  if (L <= l && r <= R) return tree[k];
  int mid = (l + r) >> 1;
  return query(k << 1, l, mid, L, R) | query(k << 1 | 1, mid + 1, r, L, R);
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = (1); i <= (n); ++i) scanf("%d", &a[i]);
  for (int i = (1); i < (n); ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    g[u].push_back(v);
    g[v].push_back(u);
  }
  init();
  build_tree(1, 1, n);
  int q;
  scanf("%d", &q);
  while (q--) {
    int t, v, x;
    scanf("%d%d", &t, &v);
    if (t == 1) {
      scanf("%d", &x);
      update(1, 1, n, tin[v], tout[v], x % m);
    } else
      printf("%d\n", (query(1, 1, n, tin[v], tout[v]) & p).count());
  }
  return 0;
}
