#include <bits/stdc++.h>
#define ll long long
#define N 100005
#define ls(a) (a<<1)
#define rs(a) (a<<1|1)
using namespace std;
const int INF = 0x7fffffff;
int n, m, q;
ll num[N];
struct segtree {
int l, r;
ll val, tag1, tag2;
} a[N << 2];
void pushup(int now) {
a[now].val = (a[ls(now)].val + a[rs(now)].val) % m;
}
void build(int now, int x, int y) {
a[now].l = x;
a[now].r = y;
a[now].tag2 = 1;
if (x == y) {
a[now].val = num[x] % m;
return;
}
int mid = (x + y) >> 1;
build(ls(now), x, mid);
build(rs(now), mid + 1, y);
pushup(now);
}
void pushdown(int now) {
int ls = ls(now), rs = rs(now);
int val = a[now].val % m, tag1 = a[now].tag1 % m, tag2 = a[now].tag2 % m;
a[ls].val = (a[ls].val * tag2 % m + tag1 * (a[ls].r - a[ls].l + 1) % m) % m;
a[rs].val = (a[rs].val * tag2 % m + tag1 * (a[rs].r - a[rs].l + 1) % m) % m;
a[ls].tag1 = (a[ls].tag1 * tag2 % m + tag1) % m;
a[rs].tag1 = (a[rs].tag1 * tag2 % m + tag1) % m;
a[ls].tag2 = a[ls].tag2 * tag2 % m;
a[rs].tag2 = a[rs].tag2 * tag2 % m;
a[now].tag1 = 0;
a[now].tag2 = 1;
}
void update1(int now, int x, int y, ll k) {
if (x <= a[now].l && a[now].r <= y) {
a[now].val = (a[now].val + k * (a[now].r - a[now].l + 1)) % m;
a[now].tag1 = (a[now].tag1 + k) % m;
} else if (!(x > a[now].r || y < a[now].l)) {
pushdown(now);
update1(ls(now), x, y, k);
update1(rs(now), x, y, k);
pushup(now);
}
}
void update2(int now, int x, int y, ll k) {
if (x <= a[now].l && a[now].r <= y) {
a[now].val = (a[now].val % m * k) % m;
a[now].tag1 = (a[now].tag1 % m * k) % m;
a[now].tag2 = (a[now].tag2 % m * k) % m;
} else if (!(x > a[now].r || y < a[now].l)) {
pushdown(now);
update2(ls(now), x, y, k);
update2(rs(now), x, y, k);
pushup(now);
}
}
ll query(int now, int x, int y) {
if (x <= a[now].l && a[now].r <= y) {
return a[now].val % m;
} else if (!(x > a[now].r || y < a[now].l)) {
pushdown(now);
return ( query(ls(now), x, y) % m + query(rs(now), x, y) % m) % m;
}
return 0;
}
int main() {
cin >> n >> q >> m;
for (int i = 1; i <= n; i++) scanf("%lld", &num[i]);
build(1, 1, n);
while (q--) {
int t, x, y;
scanf("%d%d%d", &t, &x, &y);
if (t == 1) {
ll k;
scanf("%lld", &k);
update2(1, x, y, k % m);
} else if (t == 2) {
ll k;
scanf("%lld", &k);
update1(1, x, y, k % m);
} else {
printf("%lld\n", query(1, x, y) % m);
}
}
}