#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int N = 100005;
int a[N];
int mod , n , q;
struct S{
int len , sum , lazy1 , lazy2;
void reset(){
lazy1 = 0;
lazy2 = 1;
}
};
S segt[N * 4];
S pushup(S s1 , S s2){
S s;
s.len = s1.len + s2.len;
s.len %= mod;
s.sum = s1.sum + s2.sum;
s.sum %= mod;
return s;
}
void pushdown(S& s1 , S tag){
s1.lazy1 += tag.lazy1;
s1.lazy1 %= mod;
s1.lazy2 *= tag.lazy2;
s1.lazy2 %= mod;
s1.sum *= s1.lazy2 * s1.len;
s1.sum %= mod;
s1.reset();
}
void build(int idx , int L , int R){
segt[idx].reset();
if(L == R){
segt[idx].sum = a[L];
segt[idx].len = 1;
return ;
}
int mid = (L + R) / 2;
build(idx * 2 , L , mid);
build(idx * 2 + 1 , mid + 1 , R);
segt[idx] = pushup(segt[idx * 2] , segt[idx * 2 + 1]);
}
S query(int idx , int L , int R , int ql , int qr){
if(ql <= L && R <= qr){
return segt[idx];
}
pushdown(segt[idx * 2] , segt[idx]);
pushdown(segt[idx * 2 + 1] , segt[idx]);
int m = (L + R) / 2;
segt[idx].reset();
if(qr <= m) return query(idx * 2 , L , m , ql , qr);
if(ql > m) return query(idx * 2 + 1 , m + 1 , R , ql , qr);
return pushup(query(idx * 2 , L , m , ql , qr) , query(idx * 2 + 1 , m + 1 , R , ql , qr));
}
void update(int idx , int L , int R , int ql , int qr, S tag){
if(ql <= L && R <= qr){
pushdown(segt[idx] , tag);
return ;
}
pushdown(segt[idx * 2] , segt[idx]);
pushdown(segt[idx * 2 + 1] , segt[idx]);
int m = (L + R) / 2;
segt[idx].reset();
if(ql <= m) update(idx * 2 , L , m , ql , qr , tag);
if(qr > m) update(idx * 2 + 1 , m + 1 , R , ql , qr , tag);
segt[idx] = pushup(segt[idx * 2] , segt[idx * 2 + 1]);
}
signed main(){
cin >> n >> q >> mod;
for(int i = 1 ; i <= n ; i++){
cin >> a[i];
a[i] %= mod;
}
build(1,1,n);
while(q--){
int op , ql , qr;
cin >> op >> ql >> qr;
if(op == 1){
int k;
cin >> k;
S tag;
tag.reset();
tag.lazy2 = k;
update(1,1,n,ql,qr,tag);
}
else if(op == 2){
int k;
cin >> k;
S tag;
tag.reset();
tag.lazy1 = k;
update(1,1,n,ql,qr,tag);
}
else{
cout << query(1,1,n,ql,qr).sum << endl;;
}
}
}