#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef long double ldb;
typedef __int128 LL;
const ll MAXN = 1e5 + 5;
const ll MOD = 1e9 + 7;
const ll INF = INT_MAX;
const ll LINF = LLONG_MAX;
const db EPS = 1e-5;
ll n, q, m, a[MAXN];
struct node
{
ll val, multag, addtag;
} tree[MAXN << 2];
inline ll lc(ll p){
return p << 1;
}
inline ll rc(ll p){
return p << 1 | 1;
}
void pushup(ll p){
tree[p].val = (tree[lc(p)].val + tree[rc(p)].val) % m;
}
void build(ll p, ll l, ll r){
tree[p].multag = 1;
tree[p].addtag = 0;
if (l == r){
tree[p].val = a[l] % m;
return;
}
ll mid = (l + r) >> 1;
build(lc(p), l, mid);
build(rc(p), mid + 1, r);
pushup(p);
}
void movetag(ll p, ll l, ll r, ll multag, ll addtag){
tree[p].val = (tree[p].val * multag + addtag * (r - l + 1)) % m;
tree[p].addtag = (tree[p].addtag * multag + addtag) % m;
tree[p].multag = (tree[p].multag * multag) % m;
}
void pushdown(ll p, ll l, ll r){
ll mid = (l + r) >> 1;
movetag(lc(p), l, mid, tree[p].multag, tree[p].addtag);
movetag(rc(p), mid + 1, r, tree[p].multag, tree[p].addtag);
tree[p].multag = 1;
tree[p].addtag = 0;
}
ll query(ll p, ll l, ll r, ll ql, ll qr){
if (ql <= l && r <= qr){
return tree[p].val % m;
}
pushdown(p, l, r);
ll mid = (l + r) >> 1, res = 0;
if (ql <= mid){
res = (res + query(lc(p), l, mid, ql, qr)) % m;
}
if (qr > mid){
res = (res + query(rc(p), mid + 1, r, ql, qr)) % m;
}
return res;
}
void addupdate(ll p, ll l, ll r, ll ql, ll qr, ll k){
if (ql <= l && r <= qr){
tree[p].val = (tree[p].val + k * (r - l + 1)) % m;
tree[p].addtag = (tree[p].addtag + k) % m;
return;
}
pushdown(p, l, r);
ll mid = (l + r) >> 1;
if (ql <= mid){
addupdate(lc(p), l, mid, ql, qr, k);
}
if (qr > mid){
addupdate(rc(p), mid + 1, r, ql, qr, k);
}
pushup(p);
}
void mulupdate(ll p, ll l, ll r, ll ql, ll qr, ll k){
if (ql <= l && r <= qr){
tree[p].val = (tree[p].val * k) % m;
tree[p].multag = (tree[p].multag * k) % m;
return;
}
pushdown(p, l, r);
ll mid = (l + r) >> 1;
if (ql <= mid){
mulupdate(lc(p), l, mid, ql, qr, k);
}
if (qr > mid){
mulupdate(rc(p), mid + 1, r, ql, qr, k);
}
pushup(p);
}
int main(){
cin >> n >> q >> m;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
build(1, 1, n);
while (q--){
ll op, l, r, k;
cin >> op >> l >> r;
if (op == 1){
cin >> k;
mulupdate(1, 1, n, l, r, k);
}
else if (op == 2){
cin >> k;
addupdate(1, 1, n, l, r, k);
}
else{
cout << query(1, 1, n, l, r) << endl;
}
}
return 0;
}