#include <bits/stdc++.h>
using namespace std;
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args) {
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << " : " << arg1 << " | ";
  __f(comma + 1, args...);
}
long long mod = 1e9 + 7;
void add(long long& a, long long b) {
  a += b;
  if (a >= mod) a -= mod;
  if (a < 0) a += mod;
}
long long mul(long long a, long long b) { return (a * b) % mod; }
long long mulmod(long long a, long long b, long long M) {
  if (M <= mod) return mul(a, b);
  long long res = 0;
  while (a > 0) {
    if (a & 1ll) {
      res += b;
      if (res >= M) res -= M;
    }
    a >>= 1;
    b <<= 1;
    if (b >= M) b -= M;
  }
  return res;
}
long long ffmod(long long b, long long exp, long long md = mod) {
  long long res = 1;
  while (exp) {
    if (exp & 1ll) res = (res * b) % md;
    b = (b * b) % md;
    exp /= 2ll;
  }
  return res;
}
void mxupd(pair<int, int>& a, pair<int, int> b) {
  if (a.first > b.first)
    a.second = max(a.second, b.first);
  else {
    a.second = max(a.first, b.second);
    a.first = b.first;
  }
}
const int N = 100010;
const int M = 1001;
const int LN = 20;
int st[N], en[N], A[N], B[N];
int sv[M];
vector<int> adj[N];
int m;
int tim = 0;
bitset<M> all, dummy, primes;
void dfs(int i, int p = -1) {
  st[i] = ++tim;
  B[tim] = A[i];
  for (auto ve : adj[i])
    if (p - ve) dfs(ve, i);
  en[i] = tim;
}
struct lazyseg {
  vector<bitset<M> > tr;
  vector<int> lazy;
  void init(int n) {
    tr.clear();
    lazy.clear();
    tr.resize(4 * n);
    lazy.resize(4 * n);
    build(1, 1, n);
  }
  bitset<M> merge(const bitset<M>& a, const bitset<M>& b) { return a | b; }
  void apply(bitset<M>& d, int x) { d = (((d << x) & all) | (d >> (m - x))); }
  void prop(int i, int st, int en) {
    apply(tr[i], lazy[i]);
    if (st == en) {
      lazy[i] = 0;
      return;
    }
    lazy[i + i] += lazy[i];
    lazy[i + i] %= m;
    lazy[i + i + 1] += lazy[i];
    lazy[i + i + 1] %= m;
    lazy[i] = 0;
  }
  void build(int i, int st, int en) {
    if (st == en) {
      tr[i].set(B[st]);
      return;
    }
    int mid = (st + en) >> 1;
    build(i + i, st, mid);
    build(i + i + 1, mid + 1, en);
    tr[i] = merge(tr[i + i], tr[i + i + 1]);
  }
  void upd(int i, int st, int en, int l, int r, int x) {
    if (lazy[i]) prop(i, st, en);
    if (l > en || r < st) return;
    if (l <= st && r >= en) {
      lazy[i] += x;
      if (lazy[i]) prop(i, st, en);
      return;
    }
    int mid = (st + en) >> 1;
    upd(i + i, st, mid, l, r, x);
    upd(i + i + 1, mid + 1, en, l, r, x);
    tr[i] = merge(tr[i + i], tr[i + i + 1]);
  }
  bitset<M> query(int i, int st, int en, int l, int r) {
    if (lazy[i]) prop(i, st, en);
    if (l > en || r < st) return dummy;
    if (l <= st && r >= en) {
      return tr[i];
    }
    int mid = (st + en) >> 1;
    return merge(query(i + i, st, mid, l, r),
                 query(i + i + 1, mid + 1, en, l, r));
  }
};
lazyseg seg;
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int n, i, j, k, x, q;
  int t = 1;
  cin >> n >> m;
  dummy.reset();
  for (i = 1; i <= n; i++) {
    cin >> A[i];
    A[i] %= m;
  }
  for (i = 1; i <= n - 1; i++) {
    int u, v;
    cin >> u >> v;
    adj[u].push_back(v);
    adj[v].push_back(u);
  }
  for (i = 0; i <= m - 1; i++) all.set(i);
  for (int i = 2; i < m; i++) {
    if (!sv[i]) {
      for (int j = i + i; j < m; j += i) sv[j] = 1;
      primes.set(i);
    }
  }
  dfs(1, -1);
  assert(tim == n);
  seg.init(n);
  cin >> q;
  while (q--) {
    int typ, v;
    cin >> typ;
    if (typ == 1) {
      cin >> v >> x;
      x %= m;
      seg.upd(1, 1, n, st[v], en[v], x);
    } else {
      cin >> v;
      bitset<M> ans = seg.query(1, 1, n, st[v], en[v]);
      ans = (ans & primes);
      cout << ans.count() << "\n";
    }
  }
  return 0;
}
