#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2 * 1e5 + 5;
int n, m, mod, a[N], add[N << 2], mul[N << 2], tree[N << 2];
void push_up(int cur){
tree[cur] = (tree[cur * 2] + tree[cur * 2 + 1]) % mod;
}
void addtag(int cur, int l, int r, int val){
add[cur] += val % mod;
tree[cur] += (r - l + 1) * val % mod;
return ;
}
void addtag2(int cur, int l, int r, int val){
add[cur] *= val % mod;
mul[cur] *= val % mod;
tree[cur] = tree[cur] * val % mod;
return ;
}
void push_down(int cur, int l, int r){
if(add[cur] == 0 && mul[cur] <= 1){
return ;
}
int mid = (l + r) / 2;
addtag2(cur * 2, l, mid, mul[cur]);
addtag2(cur * 2 + 1, mid + 1, r, mul[cur]);
addtag(cur * 2, l, mid, add[cur]);
addtag(cur * 2 + 1, mid + 1, r, add[cur]);
add[cur] = 0, mul[cur] = 1;
return ;
}
void build(int cur, int l, int r){
mul[cur] = 1;
if(l == r){
tree[cur] = a[l];
return ;
}
int mid = (l + r) / 2;
build(cur * 2, l, mid);
build(cur * 2 + 1, mid + 1, r);
push_up(cur);
}
int query(int cur, int l, int r, int qx, int qy){
if(qx <= l && r <= qy){
return tree[cur];
}if(qy < l || qx > r){
return 0;
}
push_down(cur, l, r);
int mid = (l + r) / 2;
return (query(cur * 2, l, mid, qx, qy) % mod + query(cur * 2 + 1, mid + 1, r, qx, qy) % mod) % mod;
}
void update1(int cur, int l, int r, int qx, int qy, int val){
if(qy < l || qx > r){
return ;
}if(qx <= l && r <= qy){
addtag2(cur, l, r, val);
return ;
}
push_down(cur, l, r);
int mid = (l + r) / 2;
update1(cur * 2, l, mid, qx, qy, val);
update1(cur * 2 + 1, mid + 1, r, qx, qy, val);
push_up(cur);
}
void update2(int cur, int l, int r, int qx, int qy, int val){
if(qy < l || qx > r){
return ;
}if(qx <= l && r <= qy){
addtag(cur, l, r, val);
return ;
}
push_down(cur, l, r);
int mid = (l + r) / 2;
update2(cur * 2, l, mid, qx, qy, val);
update2(cur * 2 + 1, mid + 1, r, qx, qy, val);
push_up(cur);
}
signed main(){
cin >> n >> m >> mod;
for(int i = 1; i <= n; i ++){
cin >> a[i];
}
build(1, 1, n);
while(m --){
int Type, x, y, k;
cin >> Type >> x >> y;
if(Type == 1){
cin >> k;
update1(1, 1, n, x, y, k);
}else if(Type == 2){
cin >> k;
update2(1, 1, n, x, y, k);
}else{
cout << query(1, 1, n, x, y) % mod << "\n";
}
}
return 0;
}