#include<iostream>
#define ll long long
using namespace std;
struct Tree{
ll L,R,sum,plus,time;
}tr[800005];
ll n,q,mod,i,opt,x,y,k;
void build(ll p,ll L,ll R){
tr[p]={L,R,0,0,1};
if(L==R) return;
ll mid=(L+R)>>1;
build(p<<1,L,mid);
build((p<<1)+1,mid+1,R);
}
void pushdown(int p){
int mid=(tr[p].L+tr[p].R)>>1;
tr[p<<1].sum=(tr[p<<1].sum*tr[p].time+tr[p].plus*(mid-tr[p].L+1))%mod;
tr[(p<<1)+1].sum=(tr[(p<<1)+1].sum*tr[p].time+tr[p].plus*(tr[p].R-mid))%mod;
tr[p<<1].time=(tr[p<<1].time*tr[p].time)%mod;
tr[(p<<1)+1].time=(tr[(p<<1)+1].time*tr[p].time)%mod;
tr[p<<1].plus=(tr[p<<1].plus*tr[p].time+tr[p].plus)%mod;
tr[(p<<1)+1].plus=(tr[(p<<1)+1].plus*tr[p].time+tr[p].plus)%mod;
tr[p].time=1;
tr[p].plus=0;
}
void modify(ll p,ll l,ll r,ll b){
if(tr[p].L>r||tr[p].R<l) return;
if(tr[p].L>=l&&tr[p].R<=r){
tr[p].plus=(tr[p].plus+b)%mod;
tr[p].sum=((tr[p].R-tr[p].L+1)*b+tr[p].sum)%mod;
return;
}
pushdown(p);
modify(p<<1,l,r,b);modify((p<<1)+1,l,r,b);
tr[p].sum=(tr[p<<1].sum+tr[(p<<1)+1].sum)%mod;
}
void modify2(ll p,ll l,ll r,ll b){
if(tr[p].L>r||tr[p].R<l) return;
if(tr[p].L>=l&&tr[p].R<=r){
tr[p].sum=(tr[p].sum*b)%mod;
tr[p].time=(tr[p].time*b)%mod;
tr[p].plus=(tr[p].plus*b)%mod;
return;
}
pushdown(p);
modify(p<<1,l,r,b);modify((p<<1)+1,l,r,b);
tr[p].sum=(tr[p<<1].sum+tr[(p<<1)+1].sum)%mod;
}
ll query(ll p,ll a,ll b){
if(tr[p].L>b||tr[p].R<a) return 0;
if(tr[p].L>=a&&tr[p].R<=b) return tr[p].sum;
pushdown(p);
return (query(p<<1,a,b)+query((p<<1)+1,a,b))%mod;
}
int main(){
cin>>n>>q>>mod;
build(1,1,n);
for(int a=1;a<=n;a++){
cin>>i;
modify(1,a,a,i);
}
for(int a=1;a<=q;a++){
cin>>opt;
if(opt==1){
cin>>x>>y>>k;
modify2(1,x,y,k);
}
else if(opt==2){
cin>>x>>y>>k;
modify(1,x,y,k);
}
else{
cin>>x>>y;
cout<<query(1,x,y)<<endl;
}
}
return 0;
}