#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 4e5 + 10;
int n, m, mod; ll a[N];
#define lch(x) ((x) << 1)
#define rch(x) (((x) << 1) | 1)
struct SegTree {
ll v, add, mul;
int l, r;
#define v(x) tr[x].v
#define add(x) tr[x].add
#define mul(x) tr[x].mul
#define l(x) tr[x].l
#define r(x) tr[x].r
};
SegTree tr[N];
void build(int p, int L, int R) {
l(p) = L; r(p) = R;
add(p) = 0; mul(p) = 1;
if(L >= R) { v(p) = a[L]; return; }
build(lch(p), L, (L + R) >> 1);
build(rch(p), 1 + ((L + R) >> 1), R);
v(p) = (v(lch(p)) + v(rch(p))) % mod;
}
void pushdown(int p) {
if(add(p) == 0 && mul(p) == 1) return;
add(lch(p)) = (add(lch(p)) * mul(p) + add(p)) % mod;
mul(lch(p)) = (mul(lch(p)) * mul(p)) % mod;
v(lch(p)) = (v(lch(p)) * mul(p) + add(p) * (r(lch(p)) - l(lch(p)) + 1)) % mod;
add(rch(p)) = (add(rch(p)) * mul(p) + add(p)) % mod;
mul(rch(p)) = (mul(rch(p)) * mul(p)) % mod;
v(rch(p)) = (v(rch(p)) * mul(p) + add(p) * (r(rch(p)) - l(rch(p)) + 1)) % mod;
add(p) = 0; mul(p) = 1;
}
void update_mul(int p, int L, int R, ll k) {
if(r(p) < L || l(p) > R) return;
if(L <= l(p) && r(p) <= R) {
add(p) *= k; add(p) %= mod;
mul(p) *= k; mul(p) %= mod;
v(p) *= k; v(p) %= mod;
return;
}
pushdown(p);
update_mul(lch(p), L, (L + R) >> 1, k);
update_mul(rch(p), ((L + R) >> 1) + 1, R, k);
v(p) = (v(lch(p)) + v(rch(p))) % mod;
}
void update_add(int p, int L, int R, ll k) {
if(r(p) < L || l(p) > R) return;
if(L <= l(p) && r(p) <= R) {
add(p) += k; add(p) %= mod; v(p) += k * (r(p) - l(p) + 1); v(p) %= mod;
return;
}
pushdown(p);
update_add(lch(p), L, R, k);
update_add(rch(p), L, R, k);
v(p) = (v(lch(p)) + v(rch(p))) % mod;
}
ll Query(int p, int L, int R) {
if(r(p) < L || l(p) > R) return 0;
if(L <= l(p) && r(p) <= R) return v(p) % mod;
pushdown(p);
return ((Query(lch(p), L, R) % mod) + (Query(rch(p), L, R) % mod)) % mod;
}
int main() {
scanf("%d%d%d", &n, &m, &mod);
for(int i = 1; i <= n; i ++ ) scanf("%lld", a + i);
build(1, 1, n);
for(int i = 1; i <= m; i ++ ) {
int op, x, y, k = 0;
scanf("%d%d%d", &op, &x, &y);
if(op == 1) {
scanf("%d", &k);
update_mul(1, x, y, k);
} else if(op == 2) {
scanf("%d", &k);
update_add(1, x, y, k);
} else
printf("%lld\n", Query(1, x, y) % mod);
}
return 0;
}