#include <bits/stdc++.h>   using namespace std;   const int bits = 1000;   bitset<bits> node[4 * 100060];   long long int leftOver[4 * 100060];   int n;   int treeSize[100060];   vector<int> adj[100060];   int dfsOrder[100060];   int o = 1;   void dfs(int curr = 1, int par = -1) {     treeSize[curr] = 1;     dfsOrder[curr] = o++;     for (int nxt : adj[curr]) {       if (nxt != par) {         dfs(nxt, curr);         treeSize[curr] += treeSize[nxt];       }     }   }   int m;   bitset<bits> rotate(std::bitset<bits> b, unsigned k) {     b = b << (k) | b >> (m - (k));     b = b | (b >> m);     return b;   }   void build(int pos, int bit, int id = 1, int l = 1, int r = n) {     if (l == r) {       node[id][bit] = 1;       return;     }     int mid = (l + r) >> 1;     if (pos <= mid)       build(pos, bit, id << 1, l, mid);     else       build(pos, bit, (id << 1) + 1, mid + 1, r);     node[id] = node[id << 1] | node[(id << 1) + 1];   }   void push(int id) {     if (leftOver[id] > 0) {       leftOver[id << 1] = (leftOver[id] + leftOver[id << 1]) % m;       leftOver[(id << 1) + 1] = (leftOver[id] + leftOver[(id << 1) + 1]) % m;       leftOver[id] = 0;     }   }   void add(int val, int L, int R, int id = 1, int l = 1, int r = n) {     if (L <= l && r <= R) {       leftOver[id] = (leftOver[id] + val) % m;       return;     }     push(id);     int mid = (l + r) >> 1;     if (L <= mid) add(val, L, R, id << 1, l, mid);     if (R > mid) add(val, L, R, (id << 1) + 1, mid + 1, r);     node[id] = rotate(node[id << 1], leftOver[id << 1]) |                rotate(node[(id << 1) + 1], leftOver[(id << 1) + 1]);   }   bitset<bits> ans;   void query(int qL, int qR, int id = 1, int l = 1, int r = n) {     if (qL <= l && qR >= r) {       ans = ans | rotate(node[id], leftOver[id]);       return;     }     push(id);     int mid = (l + r) >> 1;     if (qL <= mid) query(qL, qR, id << 1, l, mid);     if (qR > mid) query(qL, qR, (id << 1) + 1, mid + 1, r);     node[id] = rotate(node[id << 1], leftOver[id << 1]) |                rotate(node[(id << 1) + 1], leftOver[(id << 1) + 1]);   }   vector<int> primes;   vector<int> sieve(int limit) {     vector<int> primes;     bool in[limit + 1];     memset(in, true, sizeof(in));     for (int i = 2; i <= limit; i++) {       if (in[i]) {         primes.push_back(i);         for (int j = i; j <= limit; j += i) in[j] = false;       }     }     return primes;   }   int a[100060];   int aTemp[100060];   int addBrute(int l, int r, int x) {     for (int i = l; i < r + 1; i++) a[i] = (a[i] + x) % m;   }   bitset<bits> findBrute(int l, int r) {     bitset<bits> temp = 0;     for (int i = l; i < r + 1; i++) temp[a[i] % m] = 1;     return temp;   }   int main() {     ios_base::sync_with_stdio(false);     cin.tie(0);     int q;     cin >> n >> m;     primes = sieve(m);     for (int i = 0; i < n; i++) cin >> a[i + 1];     for (int i = 0; i < n - 1; i++) {       int x, y;       cin >> x >> y;       adj[x].push_back(y);       adj[y].push_back(x);     }     dfs();     for (int i = 0; i < n; i++) {       build(dfsOrder[i + 1], a[i + 1] % m);     }     for (int i = 1; i < n + 1; i++) {       aTemp[dfsOrder[i]] = a[i];     }     for (int i = 1; i < n + 1; i++) {       a[i] = aTemp[i];     }     cin >> q;     for (int i = 0; i < q; i++) {       int t, v;       cin >> t >> v;       if (t == 1) {         int x;         cin >> x;         add(x % m, dfsOrder[v], dfsOrder[v] + treeSize[v] - 1);       } else {         ans = 0;         query(dfsOrder[v], dfsOrder[v] + treeSize[v] - 1);         int k = 0;         for (int j = 0; j < primes.size(); j++) {           if (primes[j] < m) {             if (ans[primes[j]]) {               k++;             }           }         }         cout << k <<   n ;       }     }     return 0;   }