RT
#include<bits/stdc++.h>
typedef long long ll;
namespace IO {
inline int read() {
int ret = 0, f = 1;char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -f;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
ret = (ret << 1) + (ret << 3) + (ch ^ 48);
ch = getchar();
}
return ret * f;
}
void llwrite(ll x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) llwrite(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO;
using namespace std;
const int maxn = 1e5 + 5;
int n, q, mod;
int a[maxn], L[maxn << 2], R[maxn << 2];
ll sum[maxn << 2], lazyadd[maxn << 2], lazymul[maxn << 2];
int len(int x) {
return R[x] - L[x] + 1;
}
void pushup(int x) {
sum[x] = sum[x << 1] + sum[x << 1 | 1];sum[x] %= mod;
}
void pushdown(int x) {
if (lazymul[x] != 1) {
sum[x << 1] *= lazymul[x];sum[x << 1] %= mod;
sum[x << 1 | 1] *= lazymul[x];sum[x << 1 | 1] %= mod;
lazymul[x << 1] *= lazymul[x];lazymul[x << 1] %= mod;
lazymul[x << 1 | 1] *= lazymul[x];lazymul[x << 1 | 1] %= mod;
lazyadd[x << 1] *= lazymul[x];lazyadd[x << 1] %= mod;
lazyadd[x << 1 | 1] *= lazymul[x];lazyadd[x << 1 | 1] %= mod;
lazymul[x] = 1;
}
if (lazyadd[x]) {
sum[x << 1] += lazyadd[x] * len(x << 1);sum[x << 1] %= mod;
sum[x << 1 | 1] += lazyadd[x] * len(x << 1 | 1);sum[x << 1 | 1] %= mod;
lazyadd[x << 1] += lazyadd[x];lazyadd[x << 1] %= mod;
lazyadd[x << 1 | 1] += lazyadd[x];lazyadd[x << 1 | 1] %= mod;
lazyadd[x] = 0;
}
}
void build(int x, int l, int r) {
L[x] = l, R[x] = r, lazymul[x] = 1;
if (l == r) {
sum[x] = a[l];
return;
}
int mid = l + ((r - l) >> 1);
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
pushup(x);
}
ll query(int l, int r, int x) {
if (L[x] >= l && R[x] <= r) return sum[x];
pushdown(x);
ll ans = 0LL;int mid = L[x] + ((R[x] - L[x]) >> 1);
if (l <= mid) ans += query(l, r, x << 1), ans %= mod;
if (mid < r) ans += query(l, r, x << 1 | 1), ans %= mod;
return ans % mod;
}
void updateadd(int l, int r, int x, int d) {
if (L[x] >= l && R[x] <= r) {
sum[x] += d * len(x);sum[x] %= mod;
lazyadd[x] += d;lazyadd[x] %= mod;
return;
}
pushdown(x);
int mid = L[x] + ((R[x] - L[x]) >> 1);
if (l <= mid) updateadd(l, r, x << 1, d);
if (mid < r) updateadd(l, r, x << 1 | 1, d);
pushup(x);
}
void updatemul(int l, int r, int x, int d) {
if (L[x] >= l && R[x] <= r) {
lazymul[x] *= d;lazymul[x] %= d;
lazyadd[x] *= d;lazymul[x] %= d;
sum[x] *= d;sum[x] %= mod;
return;
}
pushdown(x);
int mid = L[x] + ((R[x] - L[x]) >> 1);
if (l <= mid) updatemul(l, r, x << 1, d);
if (mid < r) updatemul(l, r, x << 1 | 1, d);
pushup(x);
}
int main() {
n = read(), q = read(), mod = read();
for (int i = 1;i <= n;i++) a[i] = read();
// for (int i = 1;i <= n * 4;i++) lazymul[i] = 1;
build(1, 1, n);
while (q--) {
int op = read(), x = read(), y = read(), k;
if (op == 1) {
k = read();
updatemul(x, y, 1, k);
}
if (op == 2) {
k = read();
updateadd(x, y, 1, k);
}
if (op == 3) {
ll answer = query(x, y, 1);
llwrite(answer);puts("");
}
}
return 0;
}