#include <bits/stdc++.h>
using namespace std;
#ifndef TYOOIAIVIYDtULLYllMYA
typedef long long ll;
#endif
const int N = 1e5 + 5;
struct ST{
ll l, r, s, mul, add;
}t[N << 2];
ll n, k, p, q, x, y, op;
ll a[N];
int main(){
auto ls = [](ll u){
return u << 1;
};
auto rs = [](ll u){
return u << 1 | 1;
};
auto push_up = [&](ll u){
t[u].s = (t[ls(u)].s + t[rs(u)].s) % p;
};
auto push_down = [&](ll u){
t[ls(u)].s = (t[u].mul * t[ls(u)].s + (t[ls(u)].r - t[ls(u)].l + 1) * t[u].add % p) % p;
t[rs(u)].s = (t[u].mul * t[ls(u)].s + (t[rs(u)].r - t[rs(u)].l + 1) * t[u].add % p) % p;
t[ls(u)].mul = (t[u].mul * t[ls(u)].mul) % p;
t[rs(u)].mul = (t[u].mul * t[rs(u)].mul) % p;
t[ls(u)].add = (t[u].add + t[u].mul * t[ls(u)].add) % p;
t[rs(u)].add = (t[u].add + t[u].mul * t[rs(u)].add) % p;
t[u].add = 0;
t[u].mul = 1;
};
auto build = [&](ll u, ll l, ll r){
auto lambda = [&](ll u, ll l, ll r, auto&& self){
t[u].l = l;
t[u].r = r;
t[u].mul = 1;
if (l == r){
t[u].s = a[l] % p;
return;
}ll mid = l + r >> 1;
self(ls(u), l, mid, self);
self(rs(u), mid + 1, r, self);
};
lambda(u, l, r, lambda);
};
auto changemul = [&](ll u, ll l, ll r, ll d){
auto lambda = [&](ll u, ll l, ll r, ll d, auto&& self){
ll ll = t[u].l, rr = t[u].r, mid = ll + rr >> 1;
if (ll >= l && rr <= r){
t[u].add = t[u].add * d % p;
t[u].mul = t[u].mul * d % p;
t[u].s = t[u].s * d % p;
return;
}push_down(u);
if (l <= mid){
self(ls(u), l, r, d, self);
}if (mid < r){
self(rs(u), l, r, d, self);
}push_up(u);
};
lambda(u, l, r, d, lambda);
};
auto changeadd = [&](ll u, ll l, ll r, ll d){
auto lambda = [&](ll u, ll l, ll r, ll d, auto&& self){
ll ll = t[u].l, rr = t[u].r, mid = ll + rr >> 1;
if (ll >= l && rr <= r){
t[u].add = (t[u].add + d) % p;
t[u].s = (t[u].s + (t[u].r - t[u].l + 1) * k) % p;
return;
}push_down(u);
if (l <= mid){
self(ls(u), l, r, d, self);
}if (mid < r){
self(rs(u), l, r, d, self);
}push_up(u);
};
lambda(u, l, r, d, lambda);
};
auto query = [&](ll u, ll l, ll r){
auto lambda = [&](ll u, ll l, ll r, auto&& self){
ll lll = t[u].l, rr = t[u].r, mid = lll + rr >> 1;
if (lll >= l && rr <= r){
return t[u].s;
}push_down(u);
ll val = 0;
if (l <= mid){
val = (val + self(ls(u), l, r, self)) % p;
}if (mid < r){
val = (val + self(rs(u), l, r, self)) % p;
}return val;
};
return lambda(u, l, r, lambda);
};
scanf("%lld%lld%lld", &n, &q, &p);
for (ll i = 1; i <= n; i++){
scanf("%lld", a + i);
}build(1, 1, n);
while (q--){
scanf("%lld%lld%lld", &op, &x, &y);
if (op == 1){
scanf("%lld", &k);
changemul(1, x, y, k);
}else if (op == 2){
scanf("%lld", &k);
changeadd(1, x, y, k);
}else{
printf("%lld\n", query(1, x, y));
}
}return 0;
}