#include <bits/stdc++.h>
using namespace std;
const int MAXLEN = 1e5 + 5;
#define int long long
int n, q, mod, a[MAXLEN];
struct Segment_Tree {
int tag_a, tag_m, sum;
int l, r;
} t[MAXLEN << 2];
void pushup(int x) {
t[x].sum = (t[x << 1].sum + t[x << 1 | 1].sum) % mod;
return ;
}
void pushdown(int x) {
t[x << 1].sum = (t[x << 1].sum * t[x].tag_m + t[x].tag_a * (t[x << 1].r - t[x << 1].l + 1))%mod;
t[x << 1 | 1].sum = (t[x << 1 | 1].sum * t[x].tag_m + t[x].tag_a * (t[x << 1 | 1].r - t[x << 1 | 1].l + 1))%mod;
t[x << 1].tag_m = (t[x].tag_m * t[x << 1].tag_m) % mod;
t[x << 1 | 1].tag_m = (t[x].tag_m * t[x << 1 | 1].tag_m) % mod;
t[x << 1].tag_a = (t[x << 1].tag_a * t[x].tag_m + t[x].tag_a) % mod;
t[x << 1 | 1].tag_a = (t[x << 1 | 1].tag_a * t[x].tag_m + t[x].tag_a) % mod;
t[x].tag_a = 0;
t[x].tag_m = 1;
return ;
}
void build(int x, int l, int r) {
int mid = (l + r) >> 1;
t[x].l = l;
t[x].r = r;
t[x].tag_m = 1;
if (l == r) {
t[x].sum = a[l] % mod;
return ;
}
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
pushup(x);
return ;
}
void makeaddtag(int x, int len, int dlt) {
t[x].sum = (t[x].sum + len * dlt) % mod;
t[x].tag_a = (t[x].tag_a + dlt) % mod;
return ;
}
void makemultitag(int x, int dlt) {
t[x].sum = (t[x].sum * dlt) % mod;
t[x].tag_m = (t[x].tag_m * dlt) % mod;
t[x].tag_a = (t[x].tag_a * dlt) % mod;
return ;
}
void changeadd(int x, int l, int r, int cl, int cr, int dlt) {
if (cl <= l && r <= cr) {
makeaddtag(x, r - l + 1, dlt);
return ;
}
pushdown(x);
int mid = (l + r) >> 1;
if (l <= mid)
changeadd(x << 1, l, mid, cl, cr, dlt);
if (r > mid)
changeadd(x << 1 | 1, mid + 1, r, cl, cr, dlt);
pushup(x);
return ;
}
void changemulti(int x, int l, int r, int cl, int cr, int dlt) {
if (cl <= l && r <= cr) {
makemultitag(x, dlt);
return ;
}
pushdown(x);
int mid = (l + r) >> 1;
if (l <= mid)
changemulti(x << 1, l, mid, cl, cr, dlt);
if (r > mid)
changemulti(x << 1 | 1, mid + 1, r, cl, cr, dlt);
pushup(x);
return ;
}
int query(int x, int l, int r, int ql, int qr) {
if (ql<=l&& r <= qr) {
return t[x].sum;
}
pushdown(x);
int ret = 0;
int mid = (l + r) >> 1;
if (l <= mid)
ret = (ret + query(x << 1, l, mid, ql, qr)) % mod;
if (r > mid)
ret = (ret + query(x << 1 | 1, mid + 1, r, ql, qr)) % mod;
return ret;
}
signed main() {
scanf("%lld%lld%lld", &n, &q, &mod);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
build(1, 1, n);
for (int i = 1; i <= q; i++) {
long long x, y, k;
int opt;
scanf("%lld%lld%lld", &opt, &x, &y);
if (opt == 1) {
scanf("%lld", &k);
changemulti(1, 1, n, x, y, k);
}
if (opt == 2) {
scanf("%lld", &k);
changeadd(1, 1, n, x, y, k);
}
if (opt == 3) {
printf("%lld", query(1, 1, n, x, y));
puts("");
}
}
}