#include <bits/stdc++.h>
using namespace std;
const int INF = (int)1E9;
int N, M, MB, LASTB;
unsigned long long LASTM;
vector<int> adj[100005];
int LB, lb[100005], revlb[100005], tr[100005], a[100005], primes[1000], P;
class mask {
 public:
  unsigned long long v[16];
  mask() { memset(v, 0, sizeof(v)); }
  void set(int b) { v[b / 64] |= 1ULL << (b % 64); }
  bool has(int b) { return (v[b / 64] & (1ULL << (b % 64))) > 0; }
  void add(unsigned long long v2[16], int l, int r, unsigned long long v,
           int shift) {
    int len = r - l + 1;
    l += shift;
    r += shift;
    int li, lm, ri, rm;
    bool cross = (l < M) ^ (r < M);
    if (l >= M) l -= M;
    if (r >= M) r -= M;
    li = l / 64;
    ri = r / 64;
    lm = l % 64;
    rm = r % 64;
    if (!cross) {
      if (li == ri) {
        v2[li] |= v << lm;
      } else {
        v2[li] |= v << lm;
        v2[ri] |= v >> (len - rm - 1);
      }
    } else {
      if (li == MB - 1) {
        v2[li] |= (v << lm) & LASTM;
        v2[ri] |= v >> (len - rm - 1);
      } else {
        v2[li] |= v << lm;
        v2[MB - 1] |= (v >> (64 - lm)) & LASTM;
        v2[ri] |= v >> (len - rm - 1);
      }
    }
  }
  void shift(int shift) {
    unsigned long long v2[16] = {};
    for (int i = (0); i < (MB); i++) {
      add(v2, i * 64, min(M - 1, (i + 1) * 64 - 1), v[i], shift);
    }
    memcpy(v, v2, sizeof(v));
  }
  void combine(const mask &ano) {
    for (int i = (0); i < (MB); i++) v[i] |= ano.v[i];
  }
};
mask val[1 << 20];
int lz[1 << 20];
void build(int k, int nl, int nr) {
  if (nl == nr) {
    val[k].set(a[revlb[nl]]);
    return;
  }
  int nm = (nl + nr) >> 1;
  build(2 * k + 1, nl, nm);
  build(2 * k + 2, nm + 1, nr);
  val[k] = val[2 * k + 1];
  val[k].combine(val[2 * k + 2]);
}
void add(int k, int nl, int nr, int l, int r, int v);
void relax(int k, int nl, int nr) {
  int nm = (nl + nr) >> 1;
  add(2 * k + 1, nl, nm, nl, nm, lz[k]);
  add(2 * k + 2, nm + 1, nr, nm + 1, nr, lz[k]);
  lz[k] = 0;
}
void add(int k, int nl, int nr, int l, int r, int v) {
  if (r < nl || l > nr) return;
  if (l <= nl && nr <= r) {
    val[k].shift(v);
    lz[k] = (lz[k] + v) % M;
    return;
  }
  int nm = (nl + nr) >> 1;
  if (lz[k]) relax(k, nl, nr);
  add(2 * k + 1, nl, nm, l, r, v);
  add(2 * k + 2, nm + 1, nr, l, r, v);
  val[k] = val[2 * k + 1];
  val[k].combine(val[2 * k + 2]);
}
mask get(int k, int nl, int nr, int l, int r) {
  if (r < nl || l > nr) return mask();
  if (l <= nl && nr <= r) return val[k];
  if (lz[k]) relax(k, nl, nr);
  int nm = (nl + nr) >> 1;
  mask ml = get(2 * k + 1, nl, nm, l, r);
  mask mr = get(2 * k + 2, nm + 1, nr, l, r);
  ml.combine(mr);
  return ml;
}
void dfs(int x, int p) {
  lb[x] = LB;
  revlb[LB] = x;
  tr[x] = LB++;
  int sz = adj[x].size();
  for (int i = (0); i < (sz); i++) {
    int y = adj[x][i];
    if (y == p) continue;
    dfs(y, x);
  }
  tr[x] = LB - 1;
}
int main() {
  cin >> N >> M;
  for (int p = (2); p < (M); p++) {
    bool ok = 1;
    for (int i = 2; i * i <= p; i++) {
      if (p % i == 0) {
        ok = 0;
        break;
      }
    }
    if (ok) primes[P++] = p;
  }
  MB = (M + 64 - 1) / 64;
  LASTB = M % 64 == 0 ? 64 : M % 64;
  LASTM = (1ULL << LASTB) - 1ULL;
  for (int i = (0); i < (N); i++) {
    scanf("%d", a + i);
    a[i] %= M;
  }
  for (int i = (0); i < (N - 1); i++) {
    int a, b;
    scanf("%d%d", &a, &b);
    a--;
    b--;
    adj[a].push_back(b);
    adj[b].push_back(a);
  }
  dfs(0, -1);
  build(0, 0, N - 1);
  int Q;
  cin >> Q;
  while (Q--) {
    int t, x, val;
    scanf("%d%d", &t, &x);
    x--;
    if (t == 1) {
      scanf("%d", &val);
      add(0, 0, N - 1, lb[x], tr[x], val % M);
    } else {
      mask m = get(0, 0, N - 1, lb[x], tr[x]);
      int ans = 0;
      for (int i = (0); i < (P); i++)
        if (m.has(primes[i])) ans++;
      printf("%d\n", ans);
    }
  }
  return 0;
}
