因为mod不是质数, 所以要处理一下除的操作, 考虑吧mod分解质因数, 然后把所有数都按mod

分解出来的质因数进行拆分, 然后就能维护了。

#include<bits/stdc++.h>
#define LL long long
using namespace std;

const int N = (int)1e5 + 7;

int mod;

struct Bit {
    int a[N];
    inline void modify(int x, int v) {
        for(int i = x; i < N; i += i & -i) {
            a[i] += v;
        }
    }
    int sum(int x) {
        int ans = 0;
        for(int i = x; i; i -= i & -i) {
            ans += a[i];
        }
        return ans;
    }
};

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
struct SegmentTree {
    int sum[N << 2];
    int lazy[N << 2];
    inline void pull(int rt) {
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
        if(sum[rt] >= mod) sum[rt] -= mod;
    }
    inline void push(int rt) {
        if(lazy[rt] != 1) {
            sum[rt << 1] = 1LL * sum[rt << 1] * lazy[rt] % mod;
            sum[rt << 1 | 1] = 1LL * sum[rt << 1 | 1] * lazy[rt] % mod;
            lazy[rt << 1] = 1LL * lazy[rt << 1] * lazy[rt] % mod;
            lazy[rt << 1 | 1] = 1LL * lazy[rt << 1 | 1] * lazy[rt] % mod;
            lazy[rt] = 1;
        }
    }
    void build(int l, int r, int rt) {
        lazy[rt] = 1;
        if(l == r) {
            sum[rt] = 1;
            return;
        }
        int mid = l + r >> 1;
        build(lson); build(rson);
        pull(rt);
    }
    void update(int L, int R, int val, int l, int r, int rt) {
        if(R < l || r < L || R < L) return;
        if(L <= l && r <= R) {
            sum[rt] = 1LL * sum[rt] * val % mod;
            lazy[rt] = 1LL * lazy[rt] * val % mod;
            return;
        }
        push(rt);
        int mid = l + r >> 1;
        update(L, R, val, lson);
        update(L, R, val, rson);
        pull(rt);
    }
    void update2(int p, int val, int l, int r, int rt) {
        if(l == r) {
            sum[rt] = val;
            return;
        }
        push(rt);
        int mid = l + r >> 1;
        if(p <= mid) update2(p, val, lson);
        else update2(p, val, rson);
        pull(rt);
    }
    int query(int L, int R, int l, int r, int rt) {
        if(R < l || r < L || R < L) return 0;
        if(L <= l && r <= R) return sum[rt];
        push(rt);
        int mid = l + r >> 1;
        return (query(L, R, lson) + query(L, R, rson)) % mod;
    }
};

int n, q, a[N];
SegmentTree real_val, inv_val;
Bit bit[10];
int mul_val[N];
vector<int> F, C;
vector<int> V[N];

int power(int a, int b) {
    int ans = 1;
    while(b) {
        if(b & 1) ans = 1LL * ans * a % mod;
        a = 1LL * a * a % mod; b >>= 1;
    }
    return ans;
}

void mul_modify(int L, int R, int val) {
    if(val == 1) return;
    inv_val.update(L, R, mul_val[val], 1, n, 1);
    real_val.update(L, R, val, 1, n, 1);
    for(int i = 0; i < V[val].size(); i++) {
        if(!V[val][i]) continue;
        bit[i].modify(L, V[val][i]);
        bit[i].modify(R + 1, -V[val][i]);
    }
}

int ex_gcd(int a, int b, int &x, int &y) {
    if(b == 0) {
        x = 1; y = 0;
        return a;
    }
    int r = ex_gcd(b, a % b, x, y);
    int t = x;
    x = y; y = t - a / b * y;
    return r;
}

int inv(int a, int mod) {
    int d, x, y;
    d = ex_gcd(a, mod, x, y);
    if(d == 1) return (x % mod + mod) % mod;
    else assert(0);
}

void div_modify(int p, int val) {
    if(val == 1) return;
    for(int i = 0; i < V[val].size(); i++) {
        if(!V[val][i]) continue;
        bit[i].modify(p, -V[val][i]);
        bit[i].modify(p + 1, V[val][i]);
    }
    int gg = 1;
    for(int i = 0; i < F.size(); i++) {
        gg = 1LL * gg * power(F[i], bit[i].sum(p)) % mod;
    }
    int nex_inv = 1LL * inv_val.query(p, p, 1, n, 1) * inv(mul_val[val], mod) % mod;
    inv_val.update2(p, nex_inv, 1, n, 1);
    if(gg) real_val.update2(p, 1LL * nex_inv * gg % mod, 1, n, 1);
}

int query(int L, int R) {
    return real_val.query(L, R, 1, n, 1);
}

void show() {
    puts("");
    for(int i = 1; i <= n; i++) {
        printf("%d ", real_val.query(i, i, 1, n, 1));
    }
    puts("");
}

int main() {
    scanf("%d%d", &n, &mod);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    real_val.build(1, n, 1);
    inv_val.build(1, n, 1);
    int tmp = mod;
    for(int i = 2; i * i <= tmp; i++) {
        if(tmp % i) continue;
        F.push_back(i);
        int cnt = 0;
        while(tmp % i == 0) {
            cnt++;
            tmp /= i;
        }
        C.push_back(cnt);
    }
    if(tmp > 1) F.push_back(tmp), C.push_back(1);
    for(int i = 2; i <= 100000; i++) {
        mul_val[i] = i;
        for(auto &t : F) {
            while(mul_val[i] % t == 0) {
                mul_val[i] /= t;
            }
        }
    }
    for(int i = 2; i <= 100000; i++) {
        for(int j = 0; j < F.size(); j++) {
            int cnt = 0, now = i;
            while(now % F[j] == 0) {
                cnt++;
                now /= F[j];
            }
            V[i].push_back(cnt);
        }
    }
    for(int i = 1; i <= n; i++) {
        mul_modify(i, i, a[i]);
    }
    scanf("%d", &q);
    while(q--) {
        int op; scanf("%d", &op);
        if(op == 1) {
            int l, r, x;
            scanf("%d%d%d", &l, &r, &x);
            mul_modify(l, r, x);
        }
        else if(op == 2) {
            int p, x;
            scanf("%d%d", &p, &x);
            div_modify(p, x);
        }
        else {
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%d\n", query(l, r));
        }
    }
    return 0;
}

/*
*/
01-13 18:22