#include <stdio.h>
#include <vector>
#include <stack>
#include <bitset>
#include <string.h>
#define MAX 100000
#define MAXP 1000

using namespace std;

int m, tot, cp;
int inp1[MAX + 5], inp[MAX + 5], laz[MAX * 8 + 5], strt[MAX + 5], fin[MAX + 5], par[MAX + 5], ord[MAX + 5], prime[MAXP + 5];
bool ans[MAXP + 5], m1[MAXP + 5], vis[MAX + 5];
bitset<MAXP> se[MAX * 8 + 5];
vector<int> v[MAX + 5];

bool isprime(int x) {
    return x == 2 || (x % 2 == 1 && !m1[x]);
}

void init(int node, int b, int e) {
    int i;
    if (b == e) {
        se[node].set(inp1[b]);
        return;
    }
    init(2 * node, b, (b + e) / 2);
    init(2 * node + 1, (b + e) / 2 + 1, e);
    for (i = 0; i < m; i++) {
        if (se[2 * node][i] || se[2 * node + 1][i]) {
            se[node].set(i);
        }
    }
}

void update(int node, int b, int e, int i, int j, int val, int u) {
    int k;
    if (u > 0) {
        se[node] <<= u;
        laz[node] = (laz[node] + u) % m;
    }
    if (b > j || e < i) {
        return;
    }
    if (b >= i && e <= j) {
        if (val > 0) {
            se[node] <<= val;
            laz[node] = (laz[node] + val) % m;
        }
        return;
    }
    update(2 * node, b, (b + e) / 2, i, j, val, laz[node]);
    update(2 * node + 1, (b + e) / 2 + 1, e, i, j, val, laz[node]);
    laz[node] = 0;
    se[node].reset();
    for (k = 0; k < m; k++) {
        if (se[2 * node][k] || se[2 * node + 1][k]) {
            se[node].set(k);
        }
    }
}

void query(int node, int b, int e, int i, int j, int u) {
    int k;
    if (u > 0) {
        se[node] <<= u;
        laz[node] = (laz[node] + u) % m;
    }
    if (b > j || e < i) {
        return;
    }
    if (b >= i && e <= j) {
        for (k = 0; k < cp; k++) {
            if (se[node][prime[k]]) {
                if (!ans[prime[k]]) {
                    ans[prime[k]] = true;
                    tot++;
                }
            }
        }
        return;
    }
    query(2 * node, b, (b + e) / 2, i, j, laz[node]);
    query(2 * node + 1, (b + e) / 2 + 1, e, i, j, laz[node]);
    laz[node] = 0;
    se[node].reset();
    for (k = 0; k < m; k++) {
        if (se[2 * node][k] || se[2 * node + 1][k]) {
            se[node].set(k);
        }
    }
}

int main() {
    int n, i, j, a, b, cnt, qu, tp, x, pre;
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%d", &inp[i]);
        inp[i] %= m;
    }
    for (i = 3; i * i < m; i += 2) {
        if (m1[i]) {
            continue;
        }
        for (j = 3; i * j < m; j += 2) {
            m1[i * j] = true;
        }
    }
    cp = 0;
    if (2 < m) {
        prime[cp++] = 2;
        for (i = 3; i < m; i += 2) {
            if (!m1[i]) {
                prime[cp++] = i;
            }
        }
    }
    for (i = 0; i < n - 1; i++) {
        scanf("%d%d", &a, &b);
        v[a].push_back(b);
        v[b].push_back(a);
    }
    stack<int> st;
    cnt = 1;
    vis[1] = true;
    st.push(1);
    while (!st.empty()) {
        pre = st.top();
        strt[pre] = cnt;
        fin[pre] = cnt;
        ord[cnt++] = pre;
        st.pop();
        for (i = 0; i < v[pre].size(); i++) {
            j = v[pre][i];
            if (!vis[j]) {
                vis[j] = true;
                par[j] = pre;
                st.push(j);
            }
        }
    }
    for (i = n; i > 1; i--) {
        fin[par[ord[i]]] = max(fin[par[ord[i]]], fin[ord[i]]);
    }
    for (i = 1; i <= n; i++) {
        inp1[strt[i]] = inp[i];
    }
    init(1, 1, n);
    scanf("%d", &qu);
    while (qu--) {
        scanf("%d", &tp);
        if (tp == 1) {
            scanf("%d%d", &b, &x);
            update(1, 1, n, strt[b], fin[b], x % m, 0);
        } else {
            scanf("%d", &b);
            memset(ans, 0, sizeof(ans));
            tot = 0;
            query(1, 1, n, strt[b], fin[b], 0);
            printf("%d\n", tot);
        }
    }
    return 0;
}


#include <stdio.h>
#include <vector>
#include <stack>
#include <bitset>
#include <string.h>
#define MAX 100000
#define MAXP 1000

using namespace std;

int m, tot, cp;
int inp1[MAX + 5], inp[MAX + 5], laz[MAX * 8 + 5], strt[MAX + 5], fin[MAX + 5], par[MAX + 5], ord[MAX + 5], prime[MAXP + 5];
bool ans[MAXP + 5], m1[MAXP + 5], vis[MAX + 5];
bitset<MAXP> se[MAX * 8 + 5];
vector<int> v[MAX + 5];

void rot(bitset<MAXP>* bs, int pos) {
    bitset<MAXP> tmp;
    tmp.set();
    tmp >>= (MAXP - m);
    tmp &= (*bs);
    tmp >>= (m - pos);
    (*bs) <<= pos;
    (*bs) |= tmp;
}

void init(int node, int b, int e) {
    int i;
    if (b == e) {
        se[node].set(inp1[b]);
        return;
    }
    init(2 * node, b, (b + e) / 2);
    init(2 * node + 1, (b + e) / 2 + 1, e);
    se[node] = (se[2 * node] | se[2 * node + 1]);
}

void update(int node, int b, int e, int i, int j, int val, int u) {
    if (u > 0) {
        rot(&se[node], u);
        laz[node] = (laz[node] + u) % m;
    }
    if (b > j || e < i) {
        return;
    }
    if (b >= i && e <= j) {
        if (val > 0) {
            rot(&se[node], val);
            laz[node] = (laz[node] + val) % m;
        }
        return;
    }
    update(2 * node, b, (b + e) / 2, i, j, val, laz[node]);
    update(2 * node + 1, (b + e) / 2 + 1, e, i, j, val, laz[node]);
    laz[node] = 0;
    se[node] = (se[2 * node] | se[2 * node + 1]);
}

void query(int node, int b, int e, int i, int j, int u) {
    int k;
    if (u > 0) {
        rot(&se[node], u);
        laz[node] = (laz[node] + u) % m;
    }
    if (b > j || e < i) {
        return;
    }
    if (b >= i && e <= j) {
        for (k = 0; k < cp; k++) {
            if (se[node][prime[k]]) {
                if (!ans[prime[k]]) {
                    ans[prime[k]] = true;
                    tot++;
                }
            }
        }
        return;
    }
    query(2 * node, b, (b + e) / 2, i, j, laz[node]);
    query(2 * node + 1, (b + e) / 2 + 1, e, i, j, laz[node]);
    laz[node] = 0;
    se[node] = (se[2 * node] | se[2 * node + 1]);
}

int main() {
    int n, i, j, a, b, cnt, qu, tp, x, pre;
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%d", &inp[i]);
        inp[i] %= m;
    }
    for (i = 3; i * i < m; i += 2) {
        if (m1[i]) {
            continue;
        }
        for (j = 3; i * j < m; j += 2) {
            m1[i * j] = true;
        }
    }
    cp = 0;
    if (2 < m) {
        prime[cp++] = 2;
        for (i = 3; i < m; i += 2) {
            if (!m1[i]) {
                prime[cp++] = i;
            }
        }
    }
    for (i = 0; i < n - 1; i++) {
        scanf("%d%d", &a, &b);
        v[a].push_back(b);
        v[b].push_back(a);
    }
    stack<int> st;
    cnt = 1;
    vis[1] = true;
    st.push(1);
    while (!st.empty()) {
        pre = st.top();
        strt[pre] = cnt;
        fin[pre] = cnt;
        ord[cnt++] = pre;
        st.pop();
        for (i = 0; i < v[pre].size(); i++) {
            j = v[pre][i];
            if (!vis[j]) {
                vis[j] = true;
                par[j] = pre;
                st.push(j);
            }
        }
    }
    for (i = n; i > 1; i--) {
        fin[par[ord[i]]] = max(fin[par[ord[i]]], fin[ord[i]]);
    }
    for (i = 1; i <= n; i++) {
        inp1[strt[i]] = inp[i];
    }
    init(1, 1, n);
    scanf("%d", &qu);
    while (qu--) {
        scanf("%d", &tp);
        if (tp == 1) {
            scanf("%d%d", &b, &x);
            update(1, 1, n, strt[b], fin[b], x % m, 0);
        } else {
            scanf("%d", &b);
            memset(ans, 0, sizeof(ans));
            tot = 0;
            query(1, 1, n, strt[b], fin[b], 0);
            printf("%d\n", tot);
        }
    }
    return 0;
}


#include <stdio.h>
#include <vector>
#include <stack>
#include <bitset>
#include <string.h>
#define MAX 100000
#define MAXP 1000

using namespace std;

int m, tot, cp;
int inp1[MAX + 5], inp[MAX + 5], laz[MAX * 8 + 5], strt[MAX + 5], fin[MAX + 5], par[MAX + 5], ord[MAX + 5], prime[MAXP + 5];
bool ans[MAXP + 5], m1[MAXP + 5], vis[MAX + 5];
bitset<MAXP> se[MAX * 8 + 5];
vector<int> v[MAX + 5];

void rot(bitset<MAXP>* bs, int pos) {
    bitset<MAXP> tmp;
    tmp.set();
    tmp &= (*bs);
    tmp >>= (MAXP - pos);
    (*bs) <<= pos;
    (*bs) |= tmp;
}

void init(int node, int b, int e) {
    int i;
    if (b == e) {
        se[node].set(inp1[b]);
        return;
    }
    init(2 * node, b, (b + e) / 2);
    init(2 * node + 1, (b + e) / 2 + 1, e);
    for (i = 0; i < m; i++) {
        if (se[2 * node][i] || se[2 * node + 1][i]) {
            se[node].set(i);
        }
    }
}

void update(int node, int b, int e, int i, int j, int val, int u) {
    int k;
    if (u > 0) {
        rot(&se[node], u);
        laz[node] = (laz[node] + u) % m;
    }
    if (b > j || e < i) {
        return;
    }
    if (b >= i && e <= j) {
        if (val > 0) {
            rot(&se[node], val);
            laz[node] = (laz[node] + val) % m;
        }
        return;
    }
    update(2 * node, b, (b + e) / 2, i, j, val, laz[node]);
    update(2 * node + 1, (b + e) / 2 + 1, e, i, j, val, laz[node]);
    laz[node] = 0;
    se[node].reset();
    for (k = 0; k < m; k++) {
        if (se[2 * node][k] || se[2 * node + 1][k]) {
            se[node].set(k);
        }
    }
}

void query(int node, int b, int e, int i, int j, int u) {
    int k;
    if (u > 0) {
        rot(&se[node], u);
        laz[node] = (laz[node] + u) % m;
    }
    if (b > j || e < i) {
        return;
    }
    if (b >= i && e <= j) {
        for (k = 0; k < cp; k++) {
            if (se[node][prime[k]]) {
                if (!ans[prime[k]]) {
                    ans[prime[k]] = true;
                    tot++;
                }
            }
        }
        return;
    }
    query(2 * node, b, (b + e) / 2, i, j, laz[node]);
    query(2 * node + 1, (b + e) / 2 + 1, e, i, j, laz[node]);
    laz[node] = 0;
    se[node].reset();
    for (k = 0; k < m; k++) {
        if (se[2 * node][k] || se[2 * node + 1][k]) {
            se[node].set(k);
        }
    }
}

int main() {
    int n, i, j, a, b, cnt, qu, tp, x, pre;
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%d", &inp[i]);
        inp[i] %= m;
    }
    for (i = 3; i * i < m; i += 2) {
        if (m1[i]) {
            continue;
        }
        for (j = 3; i * j < m; j += 2) {
            m1[i * j] = true;
        }
    }
    cp = 0;
    if (2 < m) {
        prime[cp++] = 2;
        for (i = 3; i < m; i += 2) {
            if (!m1[i]) {
                prime[cp++] = i;
            }
        }
    }
    for (i = 0; i < n - 1; i++) {
        scanf("%d%d", &a, &b);
        v[a].push_back(b);
        v[b].push_back(a);
    }
    stack<int> st;
    cnt = 1;
    vis[1] = true;
    st.push(1);
    while (!st.empty()) {
        pre = st.top();
        strt[pre] = cnt;
        fin[pre] = cnt;
        ord[cnt++] = pre;
        st.pop();
        for (i = 0; i < v[pre].size(); i++) {
            j = v[pre][i];
            if (!vis[j]) {
                vis[j] = true;
                par[j] = pre;
                st.push(j);
            }
        }
    }
    for (i = n; i > 1; i--) {
        fin[par[ord[i]]] = max(fin[par[ord[i]]], fin[ord[i]]);
    }
    for (i = 1; i <= n; i++) {
        inp1[strt[i]] = inp[i];
    }
    init(1, 1, n);
    scanf("%d", &qu);
    while (qu--) {
        scanf("%d", &tp);
        if (tp == 1) {
            scanf("%d%d", &b, &x);
            update(1, 1, n, strt[b], fin[b], x % m, 0);
        } else {
            scanf("%d", &b);
            memset(ans, 0, sizeof(ans));
            tot = 0;
            query(1, 1, n, strt[b], fin[b], 0);
            printf("%d\n", tot);
        }
    }
    return 0;
}


#include <stdio.h>
#include <vector>
#include <stack>
#include <bitset>
#include <string.h>
#define MAX 100000
#define MAXP 1000

using namespace std;

int m, tot, cp;
int inp1[MAX + 5], inp[MAX + 5], laz[MAX * 8 + 5], strt[MAX + 5], fin[MAX + 5], par[MAX + 5], ord[MAX + 5], prime[MAXP + 5];
bool ans[MAXP + 5], m1[MAXP + 5], vis[MAX + 5];
bitset<MAXP> se[MAX * 8 + 5];
vector<int> v[MAX + 5];

bool isprime(int x) {
    return x == 2 || (x % 2 == 1 && !m1[x]);
}

void init(int node, int b, int e) {
    int i;
    if (b == e) {
        se[node].set(inp1[b]);
        return;
    }
    init(2 * node, b, (b + e) / 2);
    init(2 * node + 1, (b + e) / 2 + 1, e);
    for (i = 0; i < m; i++) {
        if (se[2 * node][i] || se[2 * node + 1][i]) {
            se[node].set(i);
        }
    }
}

void update(int node, int b, int e, int i, int j, int val, int u) {
    int k;
    if (u > 0) {
        bitset<MAXP> tmp;
        for (k = 0; k < m; k++) {
            if (se[node][k]) {
                tmp.set((k + u) % m);
            }
        }
        se[node] = tmp;
        laz[node] = (laz[node] + u) % m;
    }
    if (b > j || e < i) {
        return;
    }
    if (b >= i && e <= j) {
        if (val > 0) {
            bitset<MAXP> tmp;
            for (k = 0; k < m; k++) {
                if (se[node][k]) {
                    tmp.set((k + val) % m);
                }
            }
            se[node] = tmp;
            laz[node] = (laz[node] + val) % m;
        }
        return;
    }
    update(2 * node, b, (b + e) / 2, i, j, val, laz[node]);
    update(2 * node + 1, (b + e) / 2 + 1, e, i, j, val, laz[node]);
    laz[node] = 0;
    se[node].reset();
    for (k = 0; k < m; k++) {
        if (se[2 * node][k] || se[2 * node + 1][k]) {
            se[node].set(k);
        }
    }
}

void query(int node, int b, int e, int i, int j, int u) {
    int k;
    if (u > 0) {
        bitset<MAXP> tmp;
        for (k = 0; k < m; k++) {
            if (se[node][k]) {
                tmp.set((k + u) % m);
            }
        }
        se[node] = tmp;
        laz[node] = (laz[node] + u) % m;
    }
    if (b > j || e < i) {
        return;
    }
    if (b >= i && e <= j) {
        for (k = 0; k < cp; k++) {
            if (se[node][prime[k]]) {
                if (!ans[prime[k]]) {
                    ans[prime[k]] = true;
                    tot++;
                }
            }
        }
        return;
    }
    query(2 * node, b, (b + e) / 2, i, j, laz[node]);
    query(2 * node + 1, (b + e) / 2 + 1, e, i, j, laz[node]);
    laz[node] = 0;
    se[node].reset();
    for (k = 0; k < m; k++) {
        if (se[2 * node][k] || se[2 * node + 1][k]) {
            se[node].set(k);
        }
    }
}

int main() {
    int n, i, j, a, b, cnt, qu, tp, x, pre;
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++) {
        scanf("%d", &inp[i]);
        inp[i] %= m;
    }
    for (i = 3; i * i < m; i += 2) {
        if (m1[i]) {
            continue;
        }
        for (j = 3; i * j < m; j += 2) {
            m1[i * j] = true;
        }
    }
    cp = 0;
    if (2 < m) {
        prime[cp++] = 2;
        for (i = 3; i < m; i += 2) {
            if (!m1[i]) {
                prime[cp++] = i;
            }
        }
    }
    for (i = 0; i < n - 1; i++) {
        scanf("%d%d", &a, &b);
        v[a].push_back(b);
        v[b].push_back(a);
    }
    stack<int> st;
    cnt = 1;
    vis[1] = true;
    st.push(1);
    while (!st.empty()) {
        pre = st.top();
        strt[pre] = cnt;
        fin[pre] = cnt;
        ord[cnt++] = pre;
        st.pop();
        for (i = 0; i < v[pre].size(); i++) {
            j = v[pre][i];
            if (!vis[j]) {
                vis[j] = true;
                par[j] = pre;
                st.push(j);
            }
        }
    }
    for (i = n; i > 1; i--) {
        fin[par[ord[i]]] = max(fin[par[ord[i]]], fin[ord[i]]);
    }
    for (i = 1; i <= n; i++) {
        inp1[strt[i]] = inp[i];
    }
    init(1, 1, n);
    scanf("%d", &qu);
    while (qu--) {
        scanf("%d", &tp);
        if (tp == 1) {
            scanf("%d%d", &b, &x);
            update(1, 1, n, strt[b], fin[b], x % m, 0);
        } else {
            scanf("%d", &b);
            memset(ans, 0, sizeof(ans));
            tot = 0;
            query(1, 1, n, strt[b], fin[b], 0);
            printf("%d\n", tot);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, a[maxn], t[maxn<<1];
bitset<1111> r;

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    b[p] = b[p<<1] | b[p<<1|1];
}

void Rotate(int p, int x)
{
    x %= m;
    b[p] = ((b[p] << x) | (b[p] >> (m-x))) & r;
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] = (tag[p<<1] + tag[p]) % m;
        tag[p<<1|1] = (tag[p<<1|1] + tag[p]) % m;
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] = (tag[p] + v) % m;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    ret |= tmp;
    return ret;
}

//prime
int pr[1111];
bitset<1111> bb;
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) bb[pr[i]] = 1;
    for(int i = 0; i < m; i++) r[i] = 1;
}

int main(void)
{
    scanf("%d %d", &n, &m);
    GetPrime();
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = (bb & ret).count();
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, a[maxn], t[maxn<<1];

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    b[p] = b[p<<1] | b[p<<1|1];
}

void Rotate(int p, int x)
{
    x %= m;
    b[p] = (b[p] << x) | (b[p] >> (m-x));
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    ret |= tmp;
    return ret;
}

//prime
int pr[1111];
bitset<1111> bb;
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) bb[pr[i]] = 1;
}

int main(void)
{
    GetPrime();
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = (bb & ret).count();
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, a[maxn], t[maxn<<1];
bitset<1111> r;

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = timer;
//    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    b[p] = b[p<<1] | b[p<<1|1];
}

void Rotate(int p, int x)
{
    x %= m;
    b[p] = ((b[p] << x) | (b[p] >> (m-x))) & r;
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    ret |= tmp;
    return ret;
}

//prime
int pr[1111];
bitset<1111> bb;
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) bb[pr[i]] = 1;
    for(int i = 0; i < m; i++) r[i] = 1;
}

int main(void)
{
    scanf("%d %d", &n, &m);
    GetPrime();
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = (bb & ret).count();
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 4e5 + 10;
int n, m, a[maxn], t[maxn<<1];

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    for(int i = 0; i < m; i++) b[p][i] = b[p<<1][i] | b[p<<1|1][i];
}

void Rotate(int p, int x)
{
    bitset<1111> tmp;
    for(int i = 0; i < m; i++) tmp[(i+x)%m] = b[p][i];
    b[p] = tmp;
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    for(int i = 0; i < m; i++) ret[i] = ret[i] | tmp[i];
    return ret;
}

//prime
int pr[1111], p[1111];
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) p[pr[i]] = 1;
}

int main(void)
{
    GetPrime();
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = 0;
            for(int i = 2; i < m; i++) if(p[i] && ret[i]) ans++;
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, a[maxn], t[maxn<<1];

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    b[p] = b[p<<1] | b[p<<1|1];
}

void Rotate(int p, int x)
{
    x %= m;
    bitset<1111> tmp((1<<m)-1);
    b[p] = ((b[p] << x) & tmp) | (b[p] >> (m-x));
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    ret |= tmp;
    return ret;
}

//prime
int pr[1111], p[1111];
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) p[pr[i]] = 1;
}

int main(void)
{
    GetPrime();
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = 0;
            for(int i = 2; i < m; i++) if(p[i] && ret[i]) ans++;
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, a[maxn], t[maxn<<1];

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    for(int i = 0; i < m; i++) b[p][i] = b[p<<1][i] | b[p<<1|1][i];
}

void Rotate(int p, int x)
{
    bitset<1111> tmp;
    for(int i = 0; i < m; i++) tmp[(i+x)%m] = b[p][i];
    b[p] = tmp;
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    for(int i = 0; i < m; i++) ret[i] = ret[i] | tmp[i];
    return ret;
}

//prime
int pr[1111], p[1111];
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) p[pr[i]] = 1;
}

int main(void)
{
    GetPrime();
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = 0;
            for(int i = 2; i < m; i++) if(p[i] && ret[i]) ans++;
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 1e5 + 10;
int n, m, a[maxn], t[maxn<<1];

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    for(int i = 0; i < m; i++) b[p][i] = b[p<<1][i] | b[p<<1|1][i];
}

void Rotate(int p, int x)
{
    bitset<1111> tmp;
    for(int i = 0; i < m; i++) tmp[(i+x)%m] = b[p][i];
    b[p] = tmp;
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    for(int i = 0; i < m; i++) ret[i] = ret[i] | tmp[i];
    return ret;
}

//prime
int pr[1111], p[1111];
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) p[pr[i]] = 1;
}

int main(void)
{
    GetPrime();
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = 0;
            for(int i = 2; i < m; i++) if(p[i] && ret[i]) ans++;
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 4e5 + 10;
int n, m, a[maxn], t[maxn<<1];

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    for(int i = 0; i < m; i++) b[p][i] = b[p<<1][i] | b[p<<1|1][i];
}

void Rotate(int p, int x)
{
    bitset<1111> tmp;
    for(int i = 0; i < m; i++) tmp[(i+x)%m] = b[p][i];
    b[p] = tmp;
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    for(int i = 0; i < m; i++) ret[i] = ret[i] | tmp[i];
    return ret;
}

//prime
int pr[1111], p[1111];
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) p[pr[i]] = 1;
}

int main(void)
{
    GetPrime();
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            x %= m;
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = 0;
            for(int i = 2; i < m; i++) if(p[i] && ret[i]) ans++;
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, a[maxn], t[maxn<<1];

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    b[p] = b[p<<1] | b[p<<1|1];
}

void Rotate(int p, int x)
{
    x %= m;
    b[p] = (b[p] << x) | (b[p] >> (m-x));
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    ret |= tmp;
    return ret;
}

//prime
int pr[1111], p[1111];
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) p[pr[i]] = 1;
}

int main(void)
{
    GetPrime();
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = 0;
            for(int i = 2; i < m; i++) if(p[i] && ret[i]) ans++;
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, a[maxn], t[maxn<<1];
bitset<1111> r;

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    b[p] = b[p<<1] | b[p<<1|1];
}

void Rotate(int p, int x)
{
    x %= m;
    b[p] = ((b[p] << x) | (b[p] >> (m-x))) & r;
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] = (tag[p<<1] + tag[p]) % m;
        tag[p<<1|1] = (tag[p<<1|1] + tag[p]) % m;
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    ret |= tmp;
    return ret;
}

//prime
int pr[1111];
bitset<1111> bb;
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) bb[pr[i]] = 1;
    for(int i = 0; i < m; i++) r[i] = 1;
}

int main(void)
{
    scanf("%d %d", &n, &m);
    GetPrime();
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = (bb & ret).count();
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, a[maxn], t[maxn<<1];

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1001> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    b[p] = b[p<<1] | b[p<<1|1];
}

void Rotate(int p, int x)
{
    x %= m;
    b[p] = (b[p] << x) | (b[p] >> (m-x));
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    ret |= tmp;
    return ret;
}

//prime
int pr[1111];
bitset<1111> bb;
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) bb[pr[i]] = 1;
}

int main(void)
{
    GetPrime();
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = (bb & ret).count();
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, a[maxn], t[maxn<<1];
bitset<1111> r;

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    b[p] = b[p<<1] | b[p<<1|1];
}

void Rotate(int p, int x)
{
    x %= m;
    b[p] = ((b[p] << x) | (b[p] >> (m-x))) & r;
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    ret |= tmp;
    return ret;
}

//prime
int pr[1111];
bitset<1111> bb;
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) bb[pr[i]] = 1;
    for(int i = 0; i < m; i++) r[i] = 1;
}

int main(void)
{
    scanf("%d %d", &n, &m);
    GetPrime();
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = (bb & ret).count();
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
const int maxn = 2e5 + 10;
int n, m, a[maxn], t[maxn<<1];
bitset<1111> r;

//tree
int cnt, h[maxn];
struct edge
{
    int to, pre;
} e[maxn<<1];

void add(int from, int to)
{
    cnt++;
    e[cnt].pre = h[from];
    e[cnt].to = to;
    h[from] = cnt;
}

//dfs
int timer, dfn[maxn][2];
void dfs(int p, int f)
{
    dfn[p][0] = ++timer;
    t[timer] = a[p];
    for(int i = h[p]; i; i = e[i].pre)
    {
        int to = e[i].to;
        if(to == f) continue;
        dfs(to, p);
    }
    dfn[p][1] = ++timer;
    t[timer] = a[p];
}

//seg_tree
bitset<1111> b[maxn<<2];
int tag[maxn<<2];
void gather(int p)
{
    b[p] = b[p<<1] | b[p<<1|1];
}

void Rotate(int p, int x)
{
    x %= m;
    b[p] = ((b[p] << x) | (b[p] >> (m-x))) & r;
}

void push(int p)
{
    if(tag[p])
    {
        tag[p<<1] += tag[p];
        tag[p<<1|1] += tag[p];
        Rotate(p<<1, tag[p]);
        Rotate(p<<1|1, tag[p]);
        tag[p] = 0;
    }
}

void build(int p, int l, int r)
{
    tag[p] = 0;
    if(l < r)
    {
        int mid = (l + r) >> 1;
        build(p<<1, l, mid);
        build(p<<1|1, mid + 1, r);
        gather(p);
    }
    else b[p][t[l]] = 1;
}

void modify(int p, int tl, int tr, int l, int r, int v)
{
    if(tr < l || r < tl) return;
    if(l <= tl && tr <= r)
    {
        tag[p] += v;
        Rotate(p, v);
        return;
    }
    push(p);
    int mid = (tl + tr) >> 1;
    modify(p<<1, tl, mid, l, r, v);
    modify(p<<1|1, mid+1, tr, l, r, v);
    gather(p);
}

bitset<1111> query(int p, int tl, int tr, int l, int r)
{
    bitset<1111> ret, tmp;
    if(tr < l || r < tl) return ret;
    if(l <= tl && tr <= r) return b[p];
    push(p);
    int mid = (tl + tr) >> 1;
    ret = query(p<<1, tl, mid, l, r);
    tmp = query(p<<1|1, mid+1, tr, l, r);
    ret |= tmp;
    return ret;
}

//prime
int pr[1111];
bitset<1111> bb;
void GetPrime()
{
    for(int i = 2; i < 1111; i++)
    {
        if(!pr[i]) pr[++pr[0]] = i;
        for(int j = 1; j <= pr[0] && pr[j] * i < 1111; j++)
        {
            pr[i*pr[j]] = 1;
            if(i % pr[j] == 0) break;
        }
    }
    for(int i = 1; pr[i] <= 1000; i++) bb[pr[i]] = 1;
    for(int i = 0; i < m; i++) r[i] = 1;
}

int main(void)
{
    GetPrime();
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", a + i), a[i] %= m;
    for(int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    build(1, 1, timer);
    int q;
    scanf("%d", &q);
    while(q--)
    {
        int op, v, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &v, &x);
            modify(1, 1, timer, dfn[v][0], dfn[v][1], x);
        }
        else
        {
            scanf("%d", &v);
            bitset<1111> ret = query(1, 1, timer, dfn[v][0], dfn[v][1]);
            int ans = (bb & ret).count();
            printf("%d\n", ans);
        }
    }
    return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define f first
#define s second
#define mp make_pair
#define sz(a) int((a).size())
#ifdef _WIN32
#  define I64 "%I64d"
#else
#  define I64 "%lld"
#endif
#define fname "."
#define pi pair < int, int >

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

const int MAX_N = (int)1e5 + 4;
const double eps = 1e-6;
const int inf = (int)1e9 + 123;

using namespace std;

int n, m;
int a[MAX_N], st[MAX_N];
int l[MAX_N], r[MAX_N], timer;

vector < int > g[MAX_N];

void dfs(int v, int pr = -1) {
	l[v] = ++timer;
	st[timer] = v;
	for (auto to : g[v])
		if (to != pr)
			dfs(to, v);
	r[v] = timer;
}

vector < int > primes;
bool pr[MAX_N];

void init() {
	for (int i = 2; i <= m; i++) {
		if (pr[i])
			continue;
		primes.pb(i);
		for (int j = i * i; j <= m; j += i)
			pr[j] = 1;
	}
}

pair < bitset < 1005 >, int > t[4 * MAX_N];
bitset < 1005 > ones;

void build(int v = 1, int tl = 1, int tr = n) {
	if (tl == tr) {
	  t[v].f[a[st[tl]] % m] = 1;
		return;
	}
	int tm = (tl + tr) / 2;
	build(v * 2, tl, tm), build(v * 2 + 1, tm + 1, tr);
	t[v].s = 0;
	t[v].f = (t[v * 2].f | t[v * 2 + 1].f);
}

void push(int v, int tl, int tr) {
	if (!t[v].s)
		return;
	bitset < 1005 > nw = t[v].f, res;
	res.reset();
	nw >>= (m - t[v].s);
	res |= nw;
	nw = t[v].f;
	nw <<= (t[v].s);
	nw &= ones;
	res |= nw;
	t[v].f = res;
	if (tl != tr)
		t[v * 2].s = (t[v * 2].s + t[v].s) % m, t[v * 2 + 1].s = (t[v * 2 + 1].s + t[v].s) % m;
	t[v].s = 0;
}

void update(int l, int r, int val, int v = 1, int tl = 1, int tr = n) {
  push(v, tl, tr);
	if (l > r || tl > r || l > tr)
		return;
	if (tl >= l && tr <= r) {
		t[v].s = val;
		push(v, tl, tr);
		return;
	}
	int tm = (tl + tr) / 2;
	update(l, r, val, v * 2, tl, tm), update(l, r, val, v * 2 + 1, tm + 1, tr);
	t[v].f = (t[v * 2].f | t[v * 2 + 1].f);
	t[v].s = 0;
}

bitset < 1005 > res;

void get(int l, int r, int v = 1, int tl = 1, int tr = n) {
	push(v, tl, tr);
	if (l > r || tl > r || l > tr)
		return;
	if (tl >= l && tr <= r) {
	  res |= t[v].f;
		return;
	}
	int tm = (tl + tr) / 2;
	get(l, r, v * 2, tl, tm);
	get(l, r, v * 2 + 1, tm + 1, tr);
}

int main() {
	#ifdef Nick
	freopen(fname"in","r",stdin);
	freopen(fname"out","w",stdout);
	#endif
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (int i = 1, u, v; i < n; i++) {
		scanf("%d%d", &u, &v);
		g[u].pb(v), g[v].pb(u);
	}
	for (int i = 0; i < m; i++)
		ones[i] = 1;
	dfs(1);
	init();
	build();
	int query;
	scanf("%d", &query);
	for (int i = 1, tp, v, x; i <= query; i++) {
		scanf("%d", &tp);
		if (tp == 1) {
			scanf("%d%d", &v, &x);
			update(l[v], r[v], x);
		}
		else {
			scanf("%d", &v);
			res.reset();
			get(l[v], r[v]);
			int cnt = 0;
			for (auto i : primes)
				cnt += res[i];
			printf("%d\n", cnt);
		}
	}
	return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define f first
#define s second
#define mp make_pair
#define sz(a) int((a).size())
#ifdef _WIN32
#  define I64 "%I64d"
#else
#  define I64 "%lld"
#endif
#define fname "."
#define pi pair < int, int >

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

const int MAX_N = (int)1e5 + 4;
const double eps = 1e-6;
const int inf = (int)1e9 + 123;

using namespace std;

int n, m;
int a[MAX_N], st[MAX_N];
int l[MAX_N], r[MAX_N], timer;

vector < int > g[MAX_N];

void dfs(int v, int pr = -1) {
	l[v] = ++timer;
	st[timer] = v;
	for (auto to : g[v])
		if (to != pr)
			dfs(to, v);
	r[v] = timer;
}

vector < int > primes;
bool pr[MAX_N];
bitset < 1005 > prr;

void init() {
	prr.reset();
	for (int i = 2; i <= m; i++) {
		if (pr[i])
			continue;
		if (i < m)
			prr[i] = 1;
		primes.pb(i);
		for (int j = i * i; j <= m; j += i)
			pr[j] = 1;
	}
}

pair < bitset < 1005 >, int > t[4 * MAX_N];
bitset < 1005 > ones;

void build(int v = 1, int tl = 1, int tr = n) {
	if (tl == tr) {
	  t[v].f.reset();
	  t[v].f[a[st[tl]] % m] = 1;
		return;
	}
	int tm = (tl + tr) / 2;
	build(v * 2, tl, tm), build(v * 2 + 1, tm + 1, tr);
	t[v].s = 0;
	t[v].f = (t[v * 2].f | t[v * 2 + 1].f);
}

void push(int v, int tl, int tr) {
	if (!t[v].s)
		return;
	bitset < 1005 > nw = t[v].f, res;
	res.reset();
	nw >>= (m - t[v].s);
	res |= nw;
	nw = t[v].f;
	nw <<= (t[v].s);
	nw &= ones;
	res |= nw;
	t[v].f = res;
	if (tl != tr)
		t[v * 2].s = (t[v * 2].s + t[v].s) % m, t[v * 2 + 1].s = (t[v * 2 + 1].s + t[v].s) % m;
	t[v].s = 0;
}

void update(int l, int r, int val, int v = 1, int tl = 1, int tr = n) {
  push(v, tl, tr);
	if (l > r || tl > r || l > tr)
		return;
	if (tl >= l && tr <= r) {
		t[v].s = (val % m);
		push(v, tl, tr);
		return;
	}
	int tm = (tl + tr) / 2;
	update(l, r, val, v * 2, tl, tm), update(l, r, val, v * 2 + 1, tm + 1, tr);
	t[v].f = (t[v * 2].f | t[v * 2 + 1].f);
	t[v].s = 0;
}

bitset < 1005 > res;

void get(int l, int r, int v = 1, int tl = 1, int tr = n) {
	push(v, tl, tr);
	if (l > r || tl > r || l > tr)
		return;
	if (tl >= l && tr <= r) {
	  res |= t[v].f;
		return;
	}
	int tm = (tl + tr) / 2;
	get(l, r, v * 2, tl, tm);
	get(l, r, v * 2 + 1, tm + 1, tr);
}

int main() {
	#ifdef Nick
	freopen(fname"in","r",stdin);
	freopen(fname"out","w",stdout);
	#endif
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (int i = 1, u, v; i < n; i++) {
		scanf("%d%d", &u, &v);
		g[u].pb(v), g[v].pb(u);
	}
	ones.reset();
	for (int i = 0; i < m; i++)
		ones[i] = 1;
	dfs(1);
	init();
	build();
	int query;
	scanf("%d", &query);
	for (int i = 1, tp, v, x; i <= query; i++) {
		scanf("%d", &tp);
		if (tp == 1) {
			scanf("%d%d", &v, &x);
			update(l[v], r[v], x);
		}
		else {
			scanf("%d", &v);
			res.reset();
			get(l[v], r[v]);
			printf("%d\n", (res & prr).count());
		}
	}
	return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define f first
#define s second
#define mp make_pair
#define sz(a) int((a).size())
#ifdef _WIN32
#  define I64 "%I64d"
#else
#  define I64 "%lld"
#endif
#define fname "."
#define pi pair < int, int >

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

const int MAX_N = (int)1e5 + 4;
const double eps = 1e-6;
const int inf = (int)1e9 + 123;

using namespace std;

int n, m;
int a[MAX_N], st[MAX_N];
int l[MAX_N], r[MAX_N], timer;

vector < int > g[MAX_N];

void dfs(int v, int pr = -1) {
	l[v] = ++timer;
	st[timer] = v;
	for (auto to : g[v])
		if (to != pr)
			dfs(to, v);
	r[v] = timer;
}

vector < int > primes;
bool pr[MAX_N];

void init() {
	for (int i = 2; i <= m; i++) {
		if (pr[i])
			continue;
		primes.pb(i);
		for (int j = i * i; j <= m; j += i)
			pr[j] = 1;
	}
}

pair < bitset < 1005 >, int > t[4 * MAX_N];
bitset < 1005 > ones;

void build(int v = 1, int tl = 1, int tr = n) {
	if (tl == tr) {
	  t[v].f.reset();
	  t[v].f[a[st[tl]] % m] = 1;
		return;
	}
	int tm = (tl + tr) / 2;
	build(v * 2, tl, tm), build(v * 2 + 1, tm + 1, tr);
	t[v].s = 0;
	t[v].f = (t[v * 2].f | t[v * 2 + 1].f);
}

void push(int v, int tl, int tr) {
	if (!t[v].s)
		return;
	bitset < 1005 > nw = t[v].f, res;
	res.reset();
	nw >>= (m - t[v].s);
	res |= nw;
	nw = t[v].f;
	nw <<= (t[v].s);
	nw &= ones;
	res |= nw;
	t[v].f = res;
	if (tl != tr)
		t[v * 2].s = (t[v * 2].s + t[v].s) % m, t[v * 2 + 1].s = (t[v * 2 + 1].s + t[v].s) % m;
	t[v].s = 0;
}

void update(int l, int r, int val, int v = 1, int tl = 1, int tr = n) {
  push(v, tl, tr);
	if (l > r || tl > r || l > tr)
		return;
	if (tl >= l && tr <= r) {
		t[v].s = (val % m);
		push(v, tl, tr);
		return;
	}
	int tm = (tl + tr) / 2;
	update(l, r, val, v * 2, tl, tm), update(l, r, val, v * 2 + 1, tm + 1, tr);
	t[v].f = (t[v * 2].f | t[v * 2 + 1].f);
	t[v].s = 0;
}

bitset < 1005 > res;

void get(int l, int r, int v = 1, int tl = 1, int tr = n) {
	push(v, tl, tr);
	if (l > r || tl > r || l > tr)
		return;
	if (tl >= l && tr <= r) {
	  res |= t[v].f;
		return;
	}
	int tm = (tl + tr) / 2;
	get(l, r, v * 2, tl, tm);
	get(l, r, v * 2 + 1, tm + 1, tr);
}

int main() {
	#ifdef Nick
	freopen(fname"in","r",stdin);
	freopen(fname"out","w",stdout);
	#endif
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (int i = 1, u, v; i < n; i++) {
		scanf("%d%d", &u, &v);
		g[u].pb(v), g[v].pb(u);
	}
	ones.reset();
	for (int i = 0; i < m; i++)
		ones[i] = 1;
	dfs(1);
	init();
	build();
	int query;
	scanf("%d", &query);
	for (int i = 1, tp, v, x; i <= query; i++) {
		scanf("%d", &tp);
		if (tp == 1) {
			scanf("%d%d", &v, &x);
			update(l[v], r[v], x);
		}
		else {
			scanf("%d", &v);
			res.reset();
			get(l[v], r[v]);
			int cnt = 0;
			for (auto i : primes)
				cnt += res[i];
			printf("%d\n", cnt);
		}
	}
	return 0;
}


#include <bits/stdc++.h>

#define pb push_back
#define f first
#define s second
#define mp make_pair
#define sz(a) int((a).size())
#ifdef _WIN32
#  define I64 "%I64d"
#else
#  define I64 "%lld"
#endif
#define fname "."
#define pi pair < int, int >

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

const int MAX_N = (int)1e5 + 4;
const double eps = 1e-6;
const int inf = (int)1e9 + 123;

using namespace std;

int n, m;
int a[MAX_N], st[MAX_N];
int l[MAX_N], r[MAX_N], timer;

vector < int > g[MAX_N];

void dfs(int v, int pr = -1) {
	l[v] = ++timer;
	st[timer] = v;
	for (auto to : g[v])
		if (to != pr)
			dfs(to, v);
	r[v] = timer;
}

vector < int > primes;
bool pr[MAX_N];

void init() {
	for (int i = 2; i <= m; i++) {
		if (pr[i])
			continue;
		primes.pb(i);
		for (int j = i * i; j <= m; j += i)
			pr[j] = 1;
	}
}

pair < bitset < 1005 >, int > t[4 * MAX_N];
bitset < 1005 > ones;

void build(int v = 1, int tl = 1, int tr = n) {
	if (tl == tr) {
	  t[v].reset();
	  t[v].f[a[st[tl]] % m] = 1;
		return;
	}
	int tm = (tl + tr) / 2;
	build(v * 2, tl, tm), build(v * 2 + 1, tm + 1, tr);
	t[v].s = 0;
	t[v].f = (t[v * 2].f | t[v * 2 + 1].f);
}

void push(int v, int tl, int tr) {
	if (!t[v].s)
		return;
	bitset < 1005 > nw = t[v].f, res;
	res.reset();
	nw >>= (m - t[v].s);
	res |= nw;
	nw = t[v].f;
	nw <<= (t[v].s);
	nw &= ones;
	res |= nw;
	t[v].f = res;
	if (tl != tr)
		t[v * 2].s = (t[v * 2].s + t[v].s) % m, t[v * 2 + 1].s = (t[v * 2 + 1].s + t[v].s) % m;
	t[v].s = 0;
}

void update(int l, int r, int val, int v = 1, int tl = 1, int tr = n) {
  push(v, tl, tr);
	if (l > r || tl > r || l > tr)
		return;
	if (tl >= l && tr <= r) {
		t[v].s = (val % m);
		push(v, tl, tr);
		return;
	}
	int tm = (tl + tr) / 2;
	update(l, r, val, v * 2, tl, tm), update(l, r, val, v * 2 + 1, tm + 1, tr);
	t[v].f = (t[v * 2].f | t[v * 2 + 1].f);
	t[v].s = 0;
}

bitset < 1005 > res;

void get(int l, int r, int v = 1, int tl = 1, int tr = n) {
	push(v, tl, tr);
	if (l > r || tl > r || l > tr)
		return;
	if (tl >= l && tr <= r) {
	  res |= t[v].f;
		return;
	}
	int tm = (tl + tr) / 2;
	get(l, r, v * 2, tl, tm);
	get(l, r, v * 2 + 1, tm + 1, tr);
}

int main() {
	#ifdef Nick
	freopen(fname"in","r",stdin);
	freopen(fname"out","w",stdout);
	#endif
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	for (int i = 1, u, v; i < n; i++) {
		scanf("%d%d", &u, &v);
		g[u].pb(v), g[v].pb(u);
	}
	ones.reset();
	for (int i = 0; i < m; i++)
		ones[i] = 1;
	dfs(1);
	init();
	build();
	int query;
	scanf("%d", &query);
	for (int i = 1, tp, v, x; i <= query; i++) {
		scanf("%d", &tp);
		if (tp == 1) {
			scanf("%d%d", &v, &x);
			update(l[v], r[v], x);
		}
		else {
			scanf("%d", &v);
			res.reset();
			get(l[v], r[v]);
			int cnt = 0;
			for (auto i : primes)
				cnt += res[i];
			printf("%d\n", cnt);
		}
	}
	return 0;
}


#include "bits/stdc++.h"

using namespace std;

#define x first
#define y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define sqr(x) ((x)*(x))
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define NAME "parades"
#define FREOPEN freopen(NAME".in", "r", stdin); freopen(NAME".out", "w", stdout);
#define Freopen freopen("29", "r", stdin); freopen("output.txt", "w", stdout);

typedef unsigned int unt;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef long double geom;

const ll MOD = 1e9 + 7;
const int INF = 2e9;
const ll INF64 = 9e18;
const ld EPS = 1e-12;
const ld PI = 3.1415926535897932384626433832795028841;
const ll MD = 925262732;
const ll T = 634521;
const int N = 200100;
const int M = 201;

int n, m, p[N], b[N], q, tin[N], tout[N], timer = 0;
ll a[N];
bool mark[N];
vector < int > g[N], pp;
bitset < 1001 > t[N], bb;

void dfs(int v)
{
    tin[v] = ++timer;
    b[timer] = a[v] % m;
    forn(i, sz(g[v]))
        if (!tin[g[v][i]])
            dfs(g[v][i]);
    tout[v] = timer;
}

void build(int v, int tl, int tr)
{
    if (tl == tr)
        t[v][b[tl]] = 1;
    else
    {
        int tm = (tl + tr) / 2;
        build(v * 2, tl, tm);
        build(v * 2 + 1, tm + 1, tr);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

void push(int v, int tl, int tr)
{
    if (tl != tr)
    {
        p[v * 2] += p[v];
        p[v * 2] %= m;
        p[v * 2 + 1] += p[v];
        p[v * 2 + 1] %= m;
    }
    forn(i, m)
        bb[i] = 0;
    forn(i, m)
        if (t[v][i] == 1)
        {
            int q = (i + p[v]) % m;
            bb[q] = 1;
        }
    t[v] = bb;
    p[v] = 0;
}

void update(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
    {
        p[v] += val;
        p[v] %= m;
        push(v, tl, tr);
    }
    else
    {
        int tm = (tl + tr) / 2;
        update(v * 2, tl, tm, l, min(r, tm), val);
        update(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

bool get(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return 0;
    if (tl == l && tr == r)
        return t[v][val];
    else
    {
        int tm = (tl + tr) / 2;
        return get(v * 2, tl, tm, l, min(r, tm), val) | get(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 2; i < m; i++)
        if (!mark[i])
        {
            pp.pb(i);
            int j = i * i;
            while (j <= m)
            {
                mark[j] = 1;
                j += i;
            }
        }
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    forn(i, n - 1)
    {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(1);
    build(1, 1, n);
    cin >> q;
    forn(u, q)
    {
        int t;
        cin >> t;
        if (t == 1)
        {
            int v, x;
            cin >> v >> x;
            update(1, 1, n, tin[v], tout[v], x);
        }
        else
        {
            int v;
            cin >> v;
            int ans = 0;
            forn(i, sz(pp))
                if (get(1, 1, n, tin[v], tout[v], pp[i]))
                    ans++;
            cout << ans << endl;
        }
    }
    return 0;

}

/*

*/


#include "bits/stdc++.h"

using namespace std;

#define x first
#define y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define sqr(x) ((x)*(x))
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define NAME "parades"
#define FREOPEN freopen(NAME".in", "r", stdin); freopen(NAME".out", "w", stdout);
#define Freopen freopen("29", "r", stdin); freopen("output.txt", "w", stdout);

typedef unsigned int unt;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef long double geom;

const ll MOD = 1e9 + 7;
const int INF = 2e9;
const ll INF64 = 9e18;
const ld EPS = 1e-12;
const ld PI = 3.1415926535897932384626433832795028841;
const ll MD = 925262732;
const ll T = 634521;
const int N = 200100;
const int M = 201;

int n, m, p[N * 4], b[N], q, tin[N], tout[N], timer = 0;
ll a[N];
bool mark[N];
vector < int > g[N], pp;
bitset < 1000 > t[N * 4], bb, ww;

void dfs(int v)
{
    tin[v] = ++timer;
    b[timer] = a[v] % m;
    forn(i, sz(g[v]))
        if (!tin[g[v][i]])
            dfs(g[v][i]);
    tout[v] = timer;
}

void build(int v, int tl, int tr)
{
    if (tl == tr)
        t[v][b[tl]] = 1;
    else
    {
        int tm = (tl + tr) / 2;
        build(v * 2, tl, tm);
        build(v * 2 + 1, tm + 1, tr);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

void push(int v, int tl, int tr)
{
    if (tl != tr)
    {
        p[v * 2] += p[v];
        p[v * 2] %= m;
        p[v * 2 + 1] += p[v];
        p[v * 2 + 1] %= m;
    }
    p[v] %= m;
    t[v] = (t[v] << p[v]) | (t[v] >> (m - p[v]));
    p[v] = 0;
}

void update(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
    {
        p[v] += val;
        p[v] %= m;
        push(v, tl, tr);
    }
    else
    {
        int tm = (tl + tr) / 2;
        update(v * 2, tl, tm, l, min(r, tm), val);
        update(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

void get(int v, int tl, int tr, int l, int r)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
        ww = ww | t[v];
    else
    {
        int tm = (tl + tr) / 2;
        get(v * 2, tl, tm, l, min(r, tm));
        get(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 2; i <= m; i++)
        if (!mark[i])
        {
            pp.pb(i);
            int j = i * i;
            while (j <= m)
            {
                mark[j] = 1;
                j += i;
            }
        }
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    forn(i, n - 1)
    {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(1);
    build(1, 1, n);
    cin >> q;
    forn(u, q)
    {
        int t;
        cin >> t;
        if (t == 1)
        {
            int v, x;
            cin >> v >> x;
            update(1, 1, n, tin[v], tout[v], x);
        }
        else
        {
            int v;
            cin >> v;
            int ans = 0;
            ww = 0;
            get(1, 1, n, tin[v], tout[v]);
            forn(i, sz(pp))
                if (ww[pp[i]])
                    ans++;
            cout << ans << endl;
        }
        if (u > 10000)
        {
            cout << q << endl;
            return 0;
        }
    }
    return 0;

}

/*

*/


#include "bits/stdc++.h"

using namespace std;

#define x first
#define y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define sqr(x) ((x)*(x))
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define NAME "parades"
#define FREOPEN freopen(NAME".in", "r", stdin); freopen(NAME".out", "w", stdout);
#define Freopen freopen("29", "r", stdin); freopen("output.txt", "w", stdout);

typedef unsigned int unt;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef long double geom;

const ll MOD = 1e9 + 7;
const int INF = 2e9;
const ll INF64 = 9e18;
const ld EPS = 1e-12;
const ld PI = 3.1415926535897932384626433832795028841;
const ll MD = 925262732;
const ll T = 634521;
const int N = 200100;
const int M = 201;

int n, m, p[N], b[N], q, tin[N], tout[N], timer = 0;
ll a[N];
bool mark[N];
vector < int > g[N], pp;
bitset < 1001 > t[N], bb;

void dfs(int v)
{
    tin[v] = ++timer;
    b[timer] = a[v] % m;
    forn(i, sz(g[v]))
        if (!tin[g[v][i]])
            dfs(g[v][i]);
    tout[v] = timer;
}

void build(int v, int tl, int tr)
{
    if (tl == tr)
        t[v][b[tl]] = 1;
    else
    {
        int tm = (tl + tr) / 2;
        build(v * 2, tl, tm);
        build(v * 2 + 1, tm + 1, tr);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

void push(int v, int tl, int tr)
{
    if (tl != tr)
    {
        p[v * 2] += p[v];
        p[v * 2] %= m;
        p[v * 2 + 1] += p[v];
        p[v * 2 + 1] %= m;
    }
    t[v] = t[v] << p[v];
    p[v] = 0;
}

void update(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
    {
        p[v] += val;
        p[v] %= m;
        push(v, tl, tr);
    }
    else
    {
        int tm = (tl + tr) / 2;
        update(v * 2, tl, tm, l, min(r, tm), val);
        update(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

bool get(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return 0;
    if (tl == l && tr == r)
        return t[v][val];
    else
    {
        int tm = (tl + tr) / 2;
        return get(v * 2, tl, tm, l, min(r, tm), val) | get(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 2; i < m; i++)
        if (!mark[i])
        {
            pp.pb(i);
            int j = i * i;
            while (j <= m)
            {
                mark[j] = 1;
                j += i;
            }
        }
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    forn(i, n - 1)
    {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(1);
    build(1, 1, n);
    cin >> q;
    forn(u, q)
    {
        int t;
        cin >> t;
        if (t == 1)
        {
            int v, x;
            cin >> v >> x;
            update(1, 1, n, tin[v], tout[v], x);
        }
        else
        {
            int v;
            cin >> v;
            int ans = 0;
            forn(i, sz(pp))
                if (get(1, 1, n, tin[v], tout[v], pp[i]))
                    ans++;
            cout << ans << endl;
        }
    }
    return 0;

}

/*

*/


#include "bits/stdc++.h"

using namespace std;

#define x first
#define y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define sqr(x) ((x)*(x))
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define NAME "parades"
#define FREOPEN freopen(NAME".in", "r", stdin); freopen(NAME".out", "w", stdout);
#define Freopen freopen("29", "r", stdin); freopen("output.txt", "w", stdout);

typedef unsigned int unt;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef long double geom;

const ll MOD = 1e9 + 7;
const int INF = 2e9;
const ll INF64 = 9e18;
const ld EPS = 1e-12;
const ld PI = 3.1415926535897932384626433832795028841;
const ll MD = 925262732;
const ll T = 634521;
const int N = 200100;
const int M = 201;

int n, m, p[N * 4], b[N], q, tin[N], tout[N], timer = 0;
ll a[N];
bool mark[N];
vector < int > g[N], pp;
bitset < 300 > t[N * 4], bb;

void dfs(int v)
{
    tin[v] = ++timer;
    b[timer] = a[v] % m;
    forn(i, sz(g[v]))
        if (!tin[g[v][i]])
            dfs(g[v][i]);
    tout[v] = timer;
}

void build(int v, int tl, int tr)
{
    if (tl == tr)
        t[v][b[tl]] = 1;
    else
    {
        int tm = (tl + tr) / 2;
        build(v * 2, tl, tm);
        build(v * 2 + 1, tm + 1, tr);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

void push(int v, int tl, int tr)
{
    if (tl != tr)
    {
        p[v * 2] += p[v];
        p[v * 2] %= m;
        p[v * 2 + 1] += p[v];
        p[v * 2 + 1] %= m;
    }
    p[v] %= m;
    t[v] = (t[v] << p[v]) | (t[v] >> (m - p[v]));
    p[v] = 0;
}

void update(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
    {
        p[v] += val;
        p[v] %= m;
        push(v, tl, tr);
    }
    else
    {
        int tm = (tl + tr) / 2;
        update(v * 2, tl, tm, l, min(r, tm), val);
        update(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

bool get(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return 0;
    if (tl == l && tr == r)
        return t[v][val];
    else
    {
        int tm = (tl + tr) / 2;
        return get(v * 2, tl, tm, l, min(r, tm), val) | get(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 2; i < m; i++)
        if (!mark[i])
        {
            pp.pb(i);
            int j = i * i;
            while (j <= m)
            {
                mark[j] = 1;
                j += i;
            }
        }
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    forn(i, n - 1)
    {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(1);
    build(1, 1, n);
    cin >> q;
    forn(u, q)
    {
        int t;
        cin >> t;
        if (t == 1)
        {
            int v, x;
            cin >> v >> x;
            update(1, 1, n, tin[v], tout[v], x);
        }
        else
        {
            int v;
            cin >> v;
            int ans = 0;
            forn(i, sz(pp))
                if (get(1, 1, n, tin[v], tout[v], pp[i]))
                    ans++;
            cout << ans << endl;
        }
        if (u > 1000)
        {
            cout << q << endl;
            return 0;
        }
    }
    return 0;

}

/*

*/


#include "bits/stdc++.h"

using namespace std;

#define x first
#define y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define sqr(x) ((x)*(x))
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define NAME "parades"
#define FREOPEN freopen(NAME".in", "r", stdin); freopen(NAME".out", "w", stdout);
#define Freopen freopen("29", "r", stdin); freopen("output.txt", "w", stdout);

typedef unsigned int unt;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef long double geom;

const ll MOD = 1e9 + 7;
const int INF = 2e9;
const ll INF64 = 9e18;
const ld EPS = 1e-12;
const ld PI = 3.1415926535897932384626433832795028841;
const ll MD = 925262732;
const ll T = 634521;
const int N = 200100;
const int M = 201;

int n, m, p[N], b[N], q, tin[N], tout[N], timer = 0;
ll a[N];
bool mark[N];
vector < int > g[N], pp;
bitset < 300 > t[N * 4], bb;

void dfs(int v)
{
    tin[v] = ++timer;
    b[timer] = a[v] % m;
    forn(i, sz(g[v]))
        if (!tin[g[v][i]])
            dfs(g[v][i]);
    tout[v] = timer;
}

void build(int v, int tl, int tr)
{
    if (tl == tr)
        t[v][b[tl]] = 1;
    else
    {
        int tm = (tl + tr) / 2;
        build(v * 2, tl, tm);
        build(v * 2 + 1, tm + 1, tr);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

void push(int v, int tl, int tr)
{
    if (tl != tr)
    {
        p[v * 2] += p[v];
        p[v * 2] %= m;
        p[v * 2 + 1] += p[v];
        p[v * 2 + 1] %= m;
    }
    p[v] %= m;
    t[v] = (t[v] << p[v]) | (t[v] >> (m - p[v]));
    p[v] = 0;
}

void update(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
    {
        p[v] += val;
        p[v] %= m;
        push(v, tl, tr);
    }
    else
    {
        int tm = (tl + tr) / 2;
        update(v * 2, tl, tm, l, min(r, tm), val);
        update(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

bool get(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return 0;
    if (tl == l && tr == r)
        return t[v][val];
    else
    {
        int tm = (tl + tr) / 2;
        return get(v * 2, tl, tm, l, min(r, tm), val) | get(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 2; i < m; i++)
        if (!mark[i])
        {
            pp.pb(i);
            int j = i * i;
            while (j <= m)
            {
                mark[j] = 1;
                j += i;
            }
        }
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    forn(i, n - 1)
    {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(1);
    build(1, 1, n);
    cin >> q;
    forn(u, q)
    {
        int t;
        cin >> t;
        if (t == 1)
        {
            int v, x;
            cin >> v >> x;
            update(1, 1, n, tin[v], tout[v], x);
        }
        else
        {
            int v;
            cin >> v;
            int ans = 0;
            forn(i, sz(pp))
                if (get(1, 1, n, tin[v], tout[v], pp[i]))
                    ans++;
            cout << ans << endl;
        }
    }
    return 0;

}

/*

*/


#include "bits/stdc++.h"

using namespace std;

#define x first
#define y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define sqr(x) ((x)*(x))
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define NAME "parades"
#define FREOPEN freopen(NAME".in", "r", stdin); freopen(NAME".out", "w", stdout);
#define Freopen freopen("29", "r", stdin); freopen("output.txt", "w", stdout);

typedef unsigned int unt;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef long double geom;

const ll MOD = 1e9 + 7;
const int INF = 2e9;
const ll INF64 = 9e18;
const ld EPS = 1e-12;
const ld PI = 3.1415926535897932384626433832795028841;
const ll MD = 925262732;
const ll T = 634521;
const int N = 200100;
const int M = 201;

int n, m, p[N * 4], b[N], q, tin[N], tout[N], timer = 0;
ll a[N];
bool mark[N], use[N * 4], zz = 0, tt[N * 4];
vector < int > g[N], pp;
bitset < 1001 > t[N * 4], bb, ww;

void dfs(int v)
{
    tin[v] = ++timer;
    b[timer] = a[v] % m;
    forn(i, sz(g[v]))
        if (!tin[g[v][i]])
            dfs(g[v][i]);
    tout[v] = timer;
}

void build(int v, int tl, int tr)
{
    if (tl == tr)
    {
        if (a[tl] != 0)
            t[v][b[tl]] = 1;
        else
            tt[v] = 1;
    }
    else
    {
        int tm = (tl + tr) / 2;
        build(v * 2, tl, tm);
        build(v * 2 + 1, tm + 1, tr);
        t[v] = t[v * 2] | t[v * 2 + 1];
        tt[v] = tt[v * 2] | tt[v * 2 + 1];
    }
}

void push(int v, int tl, int tr)
{
    if (!use[v])
        return;
    if (tl != tr)
    {
        p[v * 2] += p[v];
        use[v * 2] = 1;
        p[v * 2] %= m;
        p[v * 2 + 1] += p[v];
        use[v * 2 + 1] = 1;
        p[v * 2 + 1] %= m;
    }
    p[v] %= m;
    t[v] = (t[v] << p[v]) | (t[v] >> (m - p[v]));
    if (tt[v])
    {
        t[v][p[v]] = 1;
        tt[v] = 0;
    }
    p[v] = 0;
}

void update(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
    {
        p[v] += val;
        use[v] = 1;
        p[v] %= m;
        push(v, tl, tr);
    }
    else
    {
        int tm = (tl + tr) / 2;
        update(v * 2, tl, tm, l, min(r, tm), val);
        update(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

void get(int v, int tl, int tr, int l, int r)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
        ww = ww | t[v];
    else
    {
        int tm = (tl + tr) / 2;
        get(v * 2, tl, tm, l, min(r, tm));
        get(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 2; i <= m; i++)
        if (!mark[i])
        {
            if (i == m)
            {
                pp.pb(0);
                zz = 1;
                break;
            }
            pp.pb(i);
            int j = i * i;
            while (j <= m)
            {
                mark[j] = 1;
                j += i;
            }
        }
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    forn(i, n - 1)
    {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(1);
    build(1, 1, n);
    cin >> q;
    forn(u, q)
    {
        int t;
        cin >> t;
        if (t == 1)
        {
            int v, x;
            cin >> v >> x;
            if (x != 0)
                update(1, 1, n, tin[v], tout[v], x);
        }
        else
        {
            int v;
            cin >> v;
            int ans = 0;
            ww = 0;
            get(1, 1, n, tin[v], tout[v]);
            forn(i, sz(pp))
                if (ww[pp[i]])
                    ans++;
            cout << ans << endl;
        }
    }
    return 0;

}

/*

*/


#include "bits/stdc++.h"

using namespace std;

#define x first
#define y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define sqr(x) ((x)*(x))
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define NAME "parades"
#define FREOPEN freopen(NAME".in", "r", stdin); freopen(NAME".out", "w", stdout);
#define Freopen freopen("29", "r", stdin); freopen("output.txt", "w", stdout);

typedef unsigned int unt;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef long double geom;

const ll MOD = 1e9 + 7;
const int INF = 2e9;
const ll INF64 = 9e18;
const ld EPS = 1e-12;
const ld PI = 3.1415926535897932384626433832795028841;
const ll MD = 925262732;
const ll T = 634521;
const int N = 200100;
const int M = 201;

int n, m, p[N], b[N], q, tin[N], tout[N], timer = 0;
ll a[N];
bool mark[N];
vector < int > g[N], pp;
bitset < 300 > t[N], bb;

void dfs(int v)
{
    tin[v] = ++timer;
    b[timer] = a[v] % m;
    forn(i, sz(g[v]))
        if (!tin[g[v][i]])
            dfs(g[v][i]);
    tout[v] = timer;
}

void build(int v, int tl, int tr)
{
    if (tl == tr)
        t[v][b[tl]] = 1;
    else
    {
        int tm = (tl + tr) / 2;
        build(v * 2, tl, tm);
        build(v * 2 + 1, tm + 1, tr);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

void push(int v, int tl, int tr)
{
    if (tl != tr)
    {
        p[v * 2] += p[v];
        p[v * 2] %= m;
        p[v * 2 + 1] += p[v];
        p[v * 2 + 1] %= m;
    }
    p[v] %= m;
    t[v] = (t[v] << p[v]) | (t[v] >> (m - p[v]));
    p[v] = 0;
}

void update(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
    {
        p[v] += val;
        p[v] %= m;
        push(v, tl, tr);
    }
    else
    {
        int tm = (tl + tr) / 2;
        update(v * 2, tl, tm, l, min(r, tm), val);
        update(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

bool get(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return 0;
    if (tl == l && tr == r)
        return t[v][val];
    else
    {
        int tm = (tl + tr) / 2;
        return get(v * 2, tl, tm, l, min(r, tm), val) | get(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 2; i < m; i++)
        if (!mark[i])
        {
            pp.pb(i);
            int j = i * i;
            while (j <= m)
            {
                mark[j] = 1;
                j += i;
            }
        }
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    forn(i, n - 1)
    {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(1);
    build(1, 1, n);
    cin >> q;
    forn(u, q)
    {
        int t;
        cin >> t;
        if (t == 1)
        {
            int v, x;
            cin >> v >> x;
            update(1, 1, n, tin[v], tout[v], x);
        }
        else
        {
            int v;
            cin >> v;
            int ans = 0;
            forn(i, sz(pp))
                if (get(1, 1, n, tin[v], tout[v], pp[i]))
                    ans++;
            cout << ans << endl;
        }
    }
    return 0;

}

/*

*/


#include "bits/stdc++.h"

using namespace std;

#define x first
#define y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define sqr(x) ((x)*(x))
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define NAME "parades"
#define FREOPEN freopen(NAME".in", "r", stdin); freopen(NAME".out", "w", stdout);
#define Freopen freopen("29", "r", stdin); freopen("output.txt", "w", stdout);

typedef unsigned int unt;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef long double geom;

const ll MOD = 1e9 + 7;
const int INF = 2e9;
const ll INF64 = 9e18;
const ld EPS = 1e-12;
const ld PI = 3.1415926535897932384626433832795028841;
const ll MD = 925262732;
const ll T = 634521;
const int N = 200100;
const int M = 201;

int n, m, p[N * 4], b[N], q, tin[N], tout[N], timer = 0;
ll a[N];
bool mark[N], use[N * 4], zz = 0, tt[N * 4];
vector < int > g[N], pp;
bitset < 1001 > t[N * 4], bb, ww;

void dfs(int v)
{
    tin[v] = ++timer;
    b[timer] = a[v] % m;
    forn(i, sz(g[v]))
        if (!tin[g[v][i]])
            dfs(g[v][i]);
    tout[v] = timer;
}

void build(int v, int tl, int tr)
{
    if (tl == tr)
    {
        t[v][b[tl]] = 1;
        return;
        if (a[tl] != 0)
            t[v][b[tl]] = 1;
        else
            tt[v] = 1;
    }
    else
    {
        int tm = (tl + tr) / 2;
        build(v * 2, tl, tm);
        build(v * 2 + 1, tm + 1, tr);
        t[v] = t[v * 2] | t[v * 2 + 1];
        tt[v] = tt[v * 2] | tt[v * 2 + 1];
    }
}

void push(int v, int tl, int tr)
{
    if (!use[v])
        return;
    if (tl != tr)
    {
        p[v * 2] += p[v];
        use[v * 2] = 1;
        p[v * 2] %= m;
        p[v * 2 + 1] += p[v];
        use[v * 2 + 1] = 1;
        p[v * 2 + 1] %= m;
    }
    p[v] %= m;
    t[v] = (t[v] << p[v]) | (t[v] >> (m - p[v]));
    if (tt[v])
    {
        t[v][p[v]] = 1;
        tt[v] = 0;
    }
    p[v] = 0;
    use[v] = 0;
}

void update(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
    {
        p[v] += val;
        use[v] = 1;
        p[v] %= m;
        push(v, tl, tr);
    }
    else
    {
        int tm = (tl + tr) / 2;
        update(v * 2, tl, tm, l, min(r, tm), val);
        update(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

void get(int v, int tl, int tr, int l, int r)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
        ww = ww | t[v];
    else
    {
        int tm = (tl + tr) / 2;
        get(v * 2, tl, tm, l, min(r, tm));
        get(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 2; i <= m; i++)
        if (!mark[i])
        {
            if (i == m)
            {
                pp.pb(0);
                zz = 1;
                break;
            }
            pp.pb(i);
            int j = i * i;
            while (j <= m)
            {
                mark[j] = 1;
                j += i;
            }
        }
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    forn(i, n - 1)
    {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(1);
    build(1, 1, n);
    cin >> q;
    forn(u, q)
    {
        int t;
        cin >> t;
        if (t == 1)
        {
            int v, x;
            cin >> v >> x;
            if (x != 0)
                update(1, 1, n, tin[v], tout[v], x);
        }
        else
        {
            int v;
            cin >> v;
            int ans = 0;
            ww = 0;
            get(1, 1, n, tin[v], tout[v]);
            forn(i, sz(pp))
                if (ww[pp[i]])
                    ans++;
            cout << ans << endl;
        }
    }
    return 0;

}

/*

*/


#include "bits/stdc++.h"

using namespace std;

#define x first
#define y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define sz(a) int((a).size())
#define sqr(x) ((x)*(x))
#define forn(i, n) for (int i = 0; i < int(n); i++)
#define NAME "parades"
#define FREOPEN freopen(NAME".in", "r", stdin); freopen(NAME".out", "w", stdout);
#define Freopen freopen("29", "r", stdin); freopen("output.txt", "w", stdout);

typedef unsigned int unt;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef long double geom;

const ll MOD = 1e9 + 7;
const int INF = 2e9;
const ll INF64 = 9e18;
const ld EPS = 1e-12;
const ld PI = 3.1415926535897932384626433832795028841;
const ll MD = 925262732;
const ll T = 634521;
const int N = 200100;
const int M = 201;

int n, m, p[N * 4], b[N], q, tin[N], tout[N], timer = 0;
ll a[N];
bool mark[N];
vector < int > g[N], pp;
bitset < 300 > t[N * 4], bb;

void dfs(int v)
{
    tin[v] = ++timer;
    b[timer] = a[v] % m;
    forn(i, sz(g[v]))
        if (!tin[g[v][i]])
            dfs(g[v][i]);
    tout[v] = timer;
}

void build(int v, int tl, int tr)
{
    if (tl == tr)
        t[v][b[tl]] = 1;
    else
    {
        int tm = (tl + tr) / 2;
        build(v * 2, tl, tm);
        build(v * 2 + 1, tm + 1, tr);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

void push(int v, int tl, int tr)
{
    if (tl != tr)
    {
        p[v * 2] += p[v];
        p[v * 2] %= m;
        p[v * 2 + 1] += p[v];
        p[v * 2 + 1] %= m;
    }
    p[v] %= m;
    t[v] = (t[v] << p[v]) | (t[v] >> (m - p[v]));
    p[v] = 0;
}

void update(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return;
    if (tl == l && tr == r)
    {
        p[v] += val;
        p[v] %= m;
        push(v, tl, tr);
    }
    else
    {
        int tm = (tl + tr) / 2;
        update(v * 2, tl, tm, l, min(r, tm), val);
        update(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
        t[v] = t[v * 2] | t[v * 2 + 1];
    }
}

bool get(int v, int tl, int tr, int l, int r, int val)
{
    push(v, tl, tr);
    if (l > r)
        return 0;
    if (tl == l && tr == r)
        return t[v][val];
    else
    {
        int tm = (tl + tr) / 2;
        return get(v * 2, tl, tm, l, min(r, tm), val) | get(v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, val);
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 2; i < m; i++)
        if (!mark[i])
        {
            pp.pb(i);
            int j = i * i;
            while (j <= m)
            {
                mark[j] = 1;
                j += i;
            }
        }
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    forn(i, n - 1)
    {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(1);
    build(1, 1, n);
    cin >> q;
    forn(u, q)
    {
        int t;
        cin >> t;
        if (t == 1)
        {
            int v, x;
            cin >> v >> x;
            update(1, 1, n, tin[v], tout[v], x);
        }
        else
        {
            int v;
            cin >> v;
            int ans = 0;
            forn(i, sz(pp))
                if (get(1, 1, n, tin[v], tout[v], pp[i]))
                    ans++;
            cout << ans << endl;
        }
    }
    return 0;

}

/*

*/