#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 100;
const int maxm = 1e3;
bitset<maxm> tree[4 * maxn];
int lazy[4 * maxn];
vector<int> graph[maxn];
int in[maxn], out[maxn], v[maxn], arr[maxn];
int m;
int cnt = 0;
void dfs(int u, int p) {
  in[u] = ++cnt;
  for (auto &x : graph[u]) {
    if (x == p) continue;
    dfs(x, u);
  }
  out[u] = cnt;
}
void push(int node, int l, int r) {
  if (lazy[node] == 0) return;
  auto k = tree[node];
  tree[node] = k << lazy[node];
  tree[node] |= k >> (m - lazy[node]);
  if (l != r) {
    lazy[2 * node] = (lazy[2 * node] + lazy[node]) % m;
    lazy[2 * node + 1] = (lazy[2 * node + 1] + lazy[node]) % m;
  }
  lazy[node] = 0;
}
void build(int node, int l, int r) {
  if (l == r) {
    tree[node].set(arr[l]);
    return;
  }
  int mid = (l + r) >> 1;
  build(2 * node, l, mid);
  build(2 * node + 1, mid + 1, r);
  tree[node] = tree[2 * node] | tree[2 * node + 1];
}
void update(int node, int l, int r, int x, int y, int val) {
  push(node, l, r);
  if (l > y || r < x) return;
  if (x <= l && r <= y) {
    lazy[node] = (lazy[node] + val) % m;
    push(node, l, r);
    return;
  }
  int mid = (l + r) >> 1;
  update(2 * node, l, mid, x, y, val);
  update(2 * node + 1, mid + 1, r, x, y, val);
  tree[node] = tree[2 * node] | tree[2 * node + 1];
}
bitset<maxm> query(int node, int l, int r, int x, int y) {
  push(node, l, r);
  if (l > y || r < x) return bitset<maxm>();
  if (x <= l && r <= y) {
    return tree[node];
  }
  int mid = (l + r) >> 1;
  return query(2 * node, l, mid, x, y) | query(2 * node + 1, mid + 1, r, x, y);
}
bool isprime(int x) {
  for (int i = 2; i * i <= x; i++) {
    if (x % i == 0) return false;
  }
  return true;
}
bitset<maxm> primes;
int main() {
  primes[0] = primes[1] = 0;
  int n;
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= n; i++) scanf("%d", &v[i]);
  for (int i = 2; i < m; i++) {
    primes[i] = isprime(i) ? 1 : 0;
  }
  for (int i = 1; i < n; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    graph[a].push_back(b);
    graph[b].push_back(a);
  }
  dfs(1, -1);
  for (int i = 1; i <= n; i++) {
    arr[in[i]] = v[i] % m;
  }
  build(1, 1, n);
  int q;
  scanf("%d", &q);
  while (q--) {
    int op;
    scanf("%d", &op);
    if (op == 1) {
      int u, x;
      scanf("%d %d", &u, &x);
      x %= m;
      update(1, 1, n, in[u], out[u], x);
    } else {
      int u;
      scanf("%d", &u);
      int ans = (query(1, 1, n, in[u], out[u]) & primes).count();
      printf("%d\n", ans);
    }
  }
  return 0;
}
