#include <iostream>
using namespace std;
const int N = 1e5 + 5;
typedef long long ll;
struct node{
int l , r;
ll val , lazy1 , lazy2;
}t[N << 2];
ll c[N],n,q,mod;
void pushup(int x){
t[x].val = (t[x << 1].val + t[x << 1 | 1].val) % mod;
}
void pushdown(int x){
if (t[x].lazy1 != 1 || t[x].lazy2){
t[x << 1].lazy1 = t[x << 1].lazy1 * t[x].lazy1 % mod;
t[x << 1 | 1].lazy1 = t[x << 1 | 1].lazy1 * t[x].lazy1 % mod;
t[x << 1].lazy2 = (t[x << 1].lazy2 * t[x].lazy1 + t[x].lazy2) % mod;
t[x << 1 | 1].lazy2 = (t[x << 1 | 1].lazy2 * t[x].lazy1 + t[x].lazy2) % mod;
t[x << 1].val = (t[x << 1].val * t[x].lazy1 + t[x].lazy2) % mod;
t[x << 1 | 1].val = (t[x << 1 | 1].val * t[x].lazy1 + t[x].lazy2) % mod;
t[x].lazy1 = 1;
t[x].lazy2 = 0;
}
}
void build(int x , int l , int r){
t[x].l = l , t[x].r = r , t[x].lazy1 = 1 , t[x].lazy2 = 0;
if (l == r){
t[x].val = c[l] % mod;
return;
}
int m = l + r >> 1;
build(x << 1 , l , m);
build(x << 1 | 1 , m + 1 , r);
pushup(x);
}
void update1(int x , int a , int b , ll v){
int l = t[x].l , r = t[x].r;
if (a <= l && r <= b){
t[x].lazy1 = (t[x].lazy1 * v) % mod;
t[x].lazy2 = (t[x].lazy2 * v) % mod;
t[x].val = (t[x].val * v) % mod;
return;
}
pushdown(x);
int m = l + r >> 1;
if (a <= m) update1(x << 1 , a , b , v);
if (m < b) update1(x << 1 | 1 , a , b , v);
pushup(x);
}
void update2(int x , int a , int b , ll v){
int l = t[x].l , r = t[x].r;
if (a <= l && r <= b){
t[x].lazy2 = (t[x].lazy2 + v) % mod;
t[x].val = (t[x].val + (r - l + 1) * v) % mod;
return;
}
pushdown(x);
int m = l + r >> 1;
if (a <= m) update2(x << 1 , a , b , v);
if (m < b) update2(x << 1 | 1 , a , b , v);
pushup(x);
}
ll query(int x , int a , int b){
int l = t[x].l , r = t[x].r;
if (a <= l && r <= b){
return t[x].val;
}
pushdown(x);
ll ans = 0;
int m = l + r >> 1;
if (a <= m) ans += query(x << 1 , a , b);
if (m < b) ans += query(x << 1 | 1 , a , b);
return ans % mod;
}
signed main(){
cin >> n >> q >> mod;
for (int i = 1;i <= n;i++) cin >> c[i];
build(1 , 1 , n);
int x,y,op;
ll z;
while (q--){
cin >> op >> x >> y;
if (op == 1){
cin >> z;
update1(1 , x , y , z % mod);
}
else if (op == 2){
cin >> z;
update2(1 , x , y , z % mod);
}
else cout << query(1 , x , y) << '\n';
}
return 0;
}