#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+100;
int n,m,x,y,z,op,ans,mod;
int a[N];
struct tree{
int l,r;
int he;
int lazy,la;
}t[N*4+100];
void down(int k){
t[k*2].he=(t[k*2].he*t[k].la+t[k].lazy*(t[k*2].r-t[k*2].l+1))%mod;
t[k*2].la=(t[k*2].la*t[k].la)%mod;
t[k*2].lazy=(t[k*2].lazy*t[k].la+t[k].lazy);
t[k*2+1].he=(t[k*2+1].he*t[k].la+t[k].lazy*(t[k*2+1].r-t[k*2+1].l+1))%mod;
t[k*2+1].la=(t[k*2+1].la*t[k].la)%mod;
t[k*2+1].lazy=(t[k*2+1].lazy*t[k].la+t[k].lazy);
t[k].lazy=0;t[k].la=1;
}
void build(int l,int r,int k){
t[k].lazy=0;t[k].la=1;
t[k].l=l;t[k].r=r;
if(l==r){
t[k].he=a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
t[k].he=(t[k*2].he+t[k*2+1].he)%mod;
}
void add1(int k){//区间修改a[x~y]*=z
if(x<=t[k].l&&t[k].r<=y){
t[k].lazy=(z*t[k].lazy)%mod;
t[k].la=(z*t[k].la)%mod;
t[k].he=(z*t[k].he)%mod;
return;
}
down(k);
int mid=(t[k].l+t[k].r)>>1;
if(x<=mid) add1(k*2);
if(y>mid) add1(k*2+1);
t[k].he=(t[k*2].he+t[k*2+1].he)%mod;
}
void add2(int k){//区间修改a[x~y]+=z
if(x<=t[k].l&&t[k].r<=y){
t[k].lazy=(t[k].lazy+z)%mod;
t[k].he+=(t[k].he+z*(t[k].r-t[k].l+1))%mod;
return;
}
down(k);
int mid=(t[k].l+t[k].r)>>1;
if(x<=mid) add2(k*2);
if(y>mid) add2(k*2+1);
t[k].he=(t[k*2].he+t[k*2+1].he)%mod;
}
void solve(int k){//区间查询x~y
if(x<=t[k].l&&t[k].r<=y){
ans=(ans+t[k].he)%mod;
return;
}
down(k);
int mid=(t[k].l+t[k].r)>>1;
if(x<=mid) solve(k*2);
if(y>mid) solve(k*2+1);
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n>>m>>mod;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,n,1);
for(int i=1;i<=m;i++){
cin>>op;
if(op==1){
cin>>x>>y>>z;
add1(1);
}else if(op==2){
cin>>x>>y>>z;
add2(1);
}else{
cin>>x>>y;
ans=0;
solve(1);
cout<<ans<<"\n";
}
}
return 0;
}