#include<bits/stdc++.h>
using namespace std;
#define I inline
const int N = 100010;
int a[N], n, m, mod;
struct node {
int l, r, ad, mu, sum;
} tr[N * 4];
I void pushup(int u) {
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
I void lzy(int u, int ad, int mu) {
tr[u].sum = tr[u].sum * mu % mod;
tr[u].ad = tr[u].ad * mu % mod;
tr[u].mu = tr[u].mu * mu % mod;
tr[u].ad = (tr[u].ad + ad) % mod;
tr[u].sum = (tr[u].sum + (tr[u].r - tr[u].l + 1) * ad) % mod;
}
I void pushdown(int u) {
lzy(u << 1, tr[u].ad, tr[u].mu);
lzy(u << 1 | 1, tr[u].ad, tr[u].mu);
tr[u].ad = 0; tr[u].mu = 1;
}
I void build(int u, int l, int r) {
tr[u].ad = 0, tr[u].mu = 1;
tr[u].l = l, tr[u].r = r;
if(l == r) {
tr[u].sum = a[l];
return ;
}
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
}
I void Add(int u, int l, int r, int x) {
if(l <= tr[u].l && tr[u].r <= r) {
tr[u].sum = (tr[u].sum + (tr[u].r - tr[u].l + 1) * x) % mod;
tr[u].ad = (tr[u].ad + x) % mod;
return ;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) Add(u << 1, l, r, x);
if(mid < r) Add(u << 1 | 1, l, r, x);
pushup(u);
}
I void Mul(int u, int l, int r, int x) {
if(l <= tr[u].l && tr[u].r <= r) {
tr[u].sum = tr[u].sum * x % mod;
tr[u].ad = tr[u].ad * x % mod;
tr[u].mu = tr[u].mu * x % mod;
return ;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) Mul(u << 1, l, r, x);
if(mid < r) Mul(u << 1 | 1, l, r, x);
pushup(u);
}
I int query(int u, int l, int r) {
int ans = 0;
if(l <= tr[u].l && tr[u].r <= r) return tr[u].sum % mod;
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) ans += query(u << 1, l, r);
if(mid < r) ans += query(u << 1 | 1, l, r);
return ans % mod;
}
int main() {
ios::sync_with_stdio(0);
cin >> n >> m >> mod;
for(int i = 1; i <= n; i++) cin >> a[i];
build(1, 1, n);
while(m--) {
int o, l, r, x;
cin >> o >> l >> r;
if(o == 3) {
cout << query(1, l, r) << '\n';
}
else {
cin >> x;
if(o == 1) Add(1, l, r, x);
else Mul(1, l, r, x);
}
}
return 0;
}