#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#define ll long long
#define FORL(a, b, c, s) for (decltype(c - b) a = b; a <= c; a += s)
#define FORR(a, b, c, s) for (decltype(c - b) a = b; a >= c; a -= s)
#define writes(x) write(x), putchar(' ')
#define writeln(x) write(x), putchar('\n')
static char buf[100000], * pa(buf), * pb(buf);
#define gc pa == pb && (pb = (pa = buf) + fread(buf, 1, 100000, stdin), pa == pb) ? EOF : *pa++
using namespace std;
template <typename T> void read(T& x) {
T t = 0, sgn = 1;
char ch = gc;
while (!isdigit(ch)) {
if (ch == '-') sgn = -sgn;
ch = gc;
}
while (isdigit(ch)) {
t = (t << 3) + (t << 1) + (ch ^ 48);
ch = gc;
}
x = sgn * t;
}
template <typename T, typename ...Args> void read(T& tmp, Args &...tmps) {
read(tmp); read(tmps...);
}
template <typename T> void write(T x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename T, typename ...Args> void write(T& tmp, Args &...tmps) {
writes(tmp);
writes(tmps...);
}
ll a[2000006], w[2000006], lzy_add[2000006], lzy_mul[200006], p;
int n, m;
struct {
int l, r;
} seg[2000006];
void build(int u, int l, int r) {
seg[u] = { l,r };
lzy_mul[u] = 1;
if (l == r) {
w[u] = a[l] % p;
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
w[u] = (w[u << 1] + w[u << 1 | 1]) % p;
}
void pushdown(int u) {
w[u << 1] = (w[u << 1] * lzy_mul[u] % p + lzy_add[u] * (seg[u << 1].r - seg[u << 1].l + 1)) % p;
w[u << 1 | 1] = (w[u << 1 | 1] * lzy_mul[u] % p + lzy_add[u] * (seg[u << 1 | 1].r - seg[u << 1 | 1].l + 1)) % p;
lzy_mul[u << 1] = (lzy_mul[u << 1] * lzy_mul[u]) % p;
lzy_mul[u << 1 | 1] = (lzy_mul[u << 1 | 1] * lzy_mul[u]) % p;
lzy_add[u << 1] = (lzy_add[u << 1] * lzy_mul[u] % p + lzy_add[u]) % p;
lzy_add[u << 1 | 1] = (lzy_add[u << 1 | 1] * lzy_mul[u] % p + lzy_add[u]) % p;
lzy_add[u] = 0;
lzy_mul[u] = 1;
}
void modify(int u, int l, int r, ll num) {
if (l <= seg[u].l && seg[u].r <= r) {
w[u] += num * (seg[u].r - seg[u].l + 1);
lzy_add[u] += num;
return;
}
pushdown(u);
int mid = (seg[u].l + seg[u].r) >> 1;
if (l <= mid) modify(u << 1, l, r, num);
if (r > mid) modify(u << 1 | 1, l, r, num);
w[u] = (w[u << 1] + w[u << 1 | 1]) % p;
}
void modify1(int u, int l, int r, ll num) {
if (l <= seg[u].l && seg[u].r <= r) {
w[u] = (w[u] * num) % p;
lzy_mul[u] = (lzy_mul[u] * num) % p;
lzy_add[u] = (lzy_add[u] * num) % p;
return;
}
pushdown(u);
int mid = (seg[u].l + seg[u].r) >> 1;
if (l <= mid) modify1(u << 1, l, r, num);
if (r > mid) modify1(u << 1 | 1, l, r, num);
w[u] = (w[u << 1] + w[u << 1 | 1]) % p;
}
ll query(int u, int l, int r) {
if (l <= seg[u].l && seg[u].r <= r) {
return w[u] % p;
}
pushdown(u);
int mid = (seg[u].l + seg[u].r) >> 1;
ll ans = 0;
if (l <= mid) ans = (ans + query(u << 1, l, r)) % p;
if (r > mid) ans = (ans + query(u << 1 | 1, l, r)) % p;
return ans;
}
int main() {
read(n, m, p);
FORL(i, 1, n, 1) read(a[i]);
build(1, 1, n);
while (m--) {
int op, l, r;
ll k;
read(op, l, r);
if (op == 1) {
read(k);
modify(1, l, r, k);
}
else if (op == 2) {
read(k);
modify1(1, l, r, k);
}
else {
writeln(query(1, l, r));
}
}
}