#include<bits/stdc++.h>
using namespace std;
int a,b,c,m[100010],o,p,q,r,s;
struct node{
int x,y,z;
};
node n[7000000];
void f(int x,int y,int z){
n[z].y=1;
if(x==y){
n[z].x=m[x];
return;
}
int mid=(x+y)/2;
f(x,mid,z*2);
f(mid+1,y,z*2+1);
n[z].x=n[z*2].x+n[z*2+1].x;
}
void g(int l,int r,int le,int ri,int x,int y){
if(le>r or ri<l){
return;
}
if(l>=le and r<=ri){
n[x].y*=y;
return;
}
n[x*2].y*=n[x].y;
n[x*2].z*=n[x].y;
n[x*2].z+=n[x].z;
n[x*2+1].y*=n[x].y;
n[x*2+1].z*=n[x].y;
n[x*2+1].z+=n[x].z;
n[x].y=1;
n[x].z=0;
int mid=(l+r)/2;
g(l,mid,le,ri,x*2,y);
g(mid+1,r,le,ri,x*2+1,y);
n[x].x=n[x*2].x*n[x*2].y+n[x*2].z*(mid-l+1)+n[x*2+1].x*n[x*2+1].y+n[x*2+1].z*(r-mid);
}
void h(int l,int r,int le,int ri,int x,int y){
if(le>r or ri<l){
return;
}
if(l>=le and r<=ri){
n[x].z+=y;
return;
}
n[x*2].y*=n[x].y;
n[x*2].z*=n[x].y;
n[x*2].z+=n[x].z;
n[x*2+1].y*=n[x].y;
n[x*2+1].z*=n[x].y;
n[x*2+1].z+=n[x].z;
n[x].y=1;
n[x].z=0;
int mid=(l+r)/2;
h(l,mid,le,ri,x*2,y);
h(mid+1,r,le,ri,x*2+1,y);
n[x].x=n[x*2].x*n[x*2].y+n[x*2].z*(mid-l+1)+n[x*2+1].x*n[x*2+1].y+n[x*2+1].z*(r-mid);
}
void j(int l,int r,int le,int ri,int x){
if(le>r or ri<l){
return;
}
int mid=(l+r)/2;
if(l>=le and r<=ri){
s+=n[x*2].x*n[x*2].y+n[x*2].z*(mid-l+1)+n[x*2+1].x*n[x*2+1].y+n[x*2+1].z*(r-mid);
s%=c;
return;
}
n[x*2].y*=n[x].y;
n[x*2].z*=n[x].y;
n[x*2].z+=n[x].z;
n[x*2+1].y*=n[x].y;
n[x*2+1].z*=n[x].y;
n[x*2+1].z+=n[x].z;
n[x].y=1;
n[x].z=0;
j(l,mid,le,ri,x*2);
j(mid+1,r,le,ri,x*2+1);
n[x].x=n[x*2].x*n[x*2].y+n[x*2].z*(mid-l+1)+n[x*2+1].x*n[x*2+1].y+n[x*2+1].z*(r-mid);
}
int main(){
cin>>a>>b>>c;
for(int i=0;i<a;i++){
cin>>m[i];
}
f(0,a-1,0);
while(b--){
cin>>o>>p>>q;
if(o==1){
cin>>r;
g(0,a-1,p-1,q-1,0,r);
}
else if(o==2){
cin>>r;
h(0,a-1,p-1,q-1,0,r);
}
else{
s=0;
j(0,a-1,p-1,q-1,0);
cout<<s-1<<endl;
}
}
return 0;
}