#include <bits/stdc++.h>
#define N 100005
using namespace std;
typedef long long ll;
int n, m, P;
ll a[N];
struct node{
int l, r, f[3];
ll d, tag, tag2;
node *ls, *rs;
void pushup() {
d = (ls->d + rs->d) % P;
}
void pushdown() {
if (f[1] == 1) {
ls->f[1] = f[1];
rs->f[1] = f[1];
ls->tag = (ls->tag + tag) % P;
ls->d = (ls->d + ls->tag * (ls->r - ls->l + 1)) % P;
rs->tag = (rs->tag + tag) % P;
rs->d = (rs->d + rs->tag * (rs->r - rs->l + 1)) % P;
f[1] = 0;
tag = 0;
if (!f[2]) return;
ls->f[2] = f[2];
rs->f[2] = f[2];
ls->tag2 = (ls->tag2 * tag2) % P;
ls->d = (ls->d * ls->tag2) % P;
rs->tag2 = (rs->tag2 * tag2) % P;
rs->d = (rs->d * rs->tag2) % P;
f[2] = 0;
tag2 = 0;
} else if (f[2] == 1) {
ls->f[2] = f[2];
rs->f[2] = f[2];
ls->tag2 = (ls->tag2 * tag2) % P;
ls->d = (ls->d * ls->tag2) % P;
rs->tag2 = (rs->tag2 * tag2) % P;
rs->d = (rs->d * rs->tag2) % P;
f[2] = 0;
tag2 = 0;
if (!f[1]) return;
ls->f[1] = f[1];
rs->f[1] = f[1];
ls->tag = (ls->tag + tag) % P;
ls->d = (ls->d + ls->tag * (ls->r - ls->l + 1)) % P;
rs->tag = (rs->tag + tag) % P;
rs->d = (rs->d + rs->tag * (rs->r - rs->l + 1)) % P;
f[1] = 0;
tag = 0;
}
}
}pool[4 * N];
int tot = 0;
node* build(int l, int r) {
node* p = pool + (++tot);
p->l = l;
p->r = r;
if (l == r) {
p->d = a[l];
return p;
}
int mid = (l + r) >> 1;
p->ls = build(l, mid);
p->rs = build(mid + 1, r);
p->pushup();
}
void update(node* p, int l, int r, int x, int op) {
if (p->l == l && p->r == r) {
if (op == 1) {
p->f[2] = p->f[1] + 1;
p->tag2 = (p->tag2 * x) * P;
p->d = (p->d * p->tag2) % P;
} else {
p->f[1] = p->f[2] + 1;
p->tag = (p->tag + x) % P;
p->d = (p->d + p->tag * (p->r - p->l + 1)) % P;
}
return;
}
p->pushdown();
int mid = (p->l + p->r) >> 1;
if (r <= mid) update(p->ls, l, r, x, op);
else if (l >= mid + 1) update(p->rs, l, r, x, op);
else {
update(p->ls, l, mid, x, op);
update(p->rs, mid + 1, r, x, op);
}
p->pushup();
}
ll query(node* p, int l, int r) {
if (p->l == l && p->r == r) {
return p->d;
}
p->pushdown();
int mid = (p->l + p->r) >> 1;
if (r <= mid) return query(p->ls, l, r);
else if (l >= mid + 1) return query(p->rs, l, r);
else return (query(p->ls, l, mid) + query(p->rs, mid + 1, r)) % P;
}
int main() {
scanf("%d%d%d", &n, &m, &P);
for (int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
node* rt = build(1, n);
while (m--) {
int op, x, y;
ll k;
scanf("%d", &op);
if (op == 1) {
scanf("%d%d%lld", &x, &y, &k);
update(rt, x, y, k, 1);
} else if (op == 2) {
scanf("%d%d%lld", &x, &y, &k);
update(rt, x, y, k, 2);
} else {
scanf("%d%d", &x, &y);
printf("%lld\n", query(rt, x, y));
}
}
return 0;
}