# include <bits/stdc++.h>
# define ll long long
# define N 100010
using namespace std;
struct Segment {
int L, R, len;
long long sum, add, mul;
} tree[N * 4];
int n, q, op, l, r;
ll x, mod;
void build (int root, int L, int R) {
tree[root].L = L, tree[root].R = R, tree[root].len = R - L + 1;
tree[root].add = 0, tree[root].mul = 1;
if (L == R) {
scanf ("%lld", &tree[root].sum);
tree[root].sum %= mod;
return ;
}
int mid = (L + R) / 2;
build (root * 2, L, mid);
build (root * 2 + 1, mid + 1, R);
tree[root].sum = (tree[root * 2].sum + tree[root * 2 + 1].sum) % mod;
}
void pushdown (int root) {
Segment l = tree[root * 2], r = tree[root * 2 + 1];
l.sum = (l.sum * tree[root].mul % mod + l.len * tree[root].add % mod) % mod;
r.sum = (r.sum * tree[root].mul % mod + r.len * tree[root].add % mod) % mod;
l.mul = (l.mul * tree[root].mul) % mod;
r.mul = (r.mul * tree[root].mul) % mod;
l.add = (l.add * tree[root].mul % mod + tree[root].add) % mod;
r.add = (r.add * tree[root].mul % mod + tree[root].add) % mod;
tree[root].mul = 1, tree[root].add = 0;
}
void Add (int root, int L, int R, long long x) {
if (L <= tree[root].L && tree[root].R <= R) {
tree[root].sum = (tree[root].sum + x * tree[root].len) % mod;
tree[root].add = (tree[root].add + x) % mod;
return ;
}
pushdown (root);
int mid = (tree[root].L + tree[root].R) / 2;
if (L <= mid) Add (root * 2, L, R, x);
if (R >= mid + 1) Add (root * 2 + 1, L, R, x);
tree[root].sum = (tree[root * 2].sum + tree[root * 2 + 1].sum) % mod;
}
void Mul (int root, int L, int R, long long x) {
if (L <= tree[root].L && tree[root].R <= R) {
tree[root].add = (tree[root].add * x) % mod;
tree[root].mul = (tree[root].mul * x) % mod;
tree[root].sum = (tree[root].sum * x) % mod;
return ;
}
pushdown (root);
int mid = (tree[root].L + tree[root].R) / 2;
if (L <= mid) Mul (root * 2, L, R, x);
if (R >= mid + 1) Mul (root * 2 + 1, L, R, x);
tree[root].sum = (tree[root * 2].sum + tree[root * 2 + 1].sum) % mod;
}
ll query (int root, int L, int R) {
if (L <= tree[root].L && tree[root].R <= R) {
return tree[root].sum;
}
pushdown (root);
int mid = (tree[root].L + tree[root].R) / 2;
long long sum = 0;
if (L <= mid) sum = (sum + query (root * 2, L, R)) % mod;
if (R >= mid + 1) sum = (sum + query (root * 2 + 1, L, R)) % mod;
return sum;
}
int main () {
scanf ("%d%d%lld", &n, &q, &mod);
build (1, 1, n);
for (int i = 1; i <= q; i ++) {
scanf ("%d%d%d", &op, &l, &r);
if (op == 1) {
scanf ("%lld", &x);
Mul (1, l, r, x);
} else if (op == 2) {
scanf ("%lld", &x);
Add (1, l, r, x);
} else printf ("%lld\n", query (1, l, r));
}
return 0;
}