#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,q;
const int MAXN=100005;
ll a[MAXN]={};
struct node{
int l,r;
ll dat,tag,tag1;
}ST[4*MAXN];
void build(int node_num,int l,int r){
ST[node_num].l=l;
ST[node_num].r=r;
ST[node_num].tag=0;
ST[node_num].tag1=1;
if(l==r){
ST[node_num].dat=a[l];
return ;
}
int mid=(l+r)/2;
build(node_num*2,l,mid);
build(node_num*2+1,mid+1,r);
ST[node_num].dat=ST[node_num*2].dat+ST[node_num*2+1].dat;
}
void push_down(int node_num){
if(ST[node_num].tag==0&&ST[node_num].tag1==0){
return ;
}
int mid=(ST[node_num].l+ST[node_num].r)/2;
ST[node_num*2].dat*=ST[node_num].tag1;
ST[node_num*2].dat+=ST[node_num].tag*(mid-ST[node_num].l+1);
ST[node_num*2].tag1*=ST[node_num].tag1;
ST[node_num*2].tag+=ST[node_num].tag;
ST[node_num*2+1].dat*=ST[node_num].tag1;
ST[node_num*2+1].dat+=ST[node_num].tag*(ST[node_num].r-mid);
ST[node_num*2+1].tag1*=ST[node_num].tag1;
ST[node_num*2+1].tag+=ST[node_num].tag;
ST[node_num].tag=0;
ST[node_num].tag1=1;
}
ll ask(int node_num,int tar_l,int tar_r){
int mid=(ST[node_num].l+ST[node_num].r)/2;
if(ST[node_num].l>=tar_l&&ST[node_num].r<=tar_r){
return ST[node_num].dat;
}
push_down(node_num);
ll res=0;
if(mid>=tar_l){
res+=ask(node_num*2,tar_l,tar_r);
res=res%q;
}
if(mid<tar_r){
res+=ask(node_num*2+1,tar_l,tar_r);
res=res%q;
}
return res;
}
void add(int node_num,int tar_l,int tar_r,ll val){
int mid=(ST[node_num].l+ST[node_num].r)/2;
if(ST[node_num].l>=tar_l&&ST[node_num].r<=tar_r){
ST[node_num].dat+=val*(ST[node_num].r-ST[node_num].l+1);
ST[node_num].tag+=val;
return ;
}
push_down(node_num);
if(mid>=tar_l){
add(node_num*2,tar_l,tar_r,val);
}
if(mid<tar_r){
add(node_num*2+1,tar_l,tar_r,val);
}
ST[node_num].dat=ST[node_num*2].dat+ST[node_num*2+1].dat;
}
void add1(int node_num,int tar_l,int tar_r,ll val){
int mid=(ST[node_num].l+ST[node_num].r)/2;
if(ST[node_num].l>=tar_l&&ST[node_num].r<=tar_r){
ST[node_num].dat*=val;
ST[node_num].tag*=val;
ST[node_num].tag1*=val;
return ;
}
push_down(node_num);
if(mid>=tar_l){
add1(node_num*2,tar_l,tar_r,val);
}
if(mid<tar_r){
add1(node_num*2+1,tar_l,tar_r,val);
}
ST[node_num].dat=ST[node_num*2].dat+ST[node_num*2+1].dat;
}
int main(){
cin>>n>>m>>q;
ll res[MAXN]={},t=1;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i=1;i<=m;i++){
int type;
cin>>type;
if(type==1){
ll xx,yy,k;
cin>>xx>>yy>>k;
add1(1,xx,yy,k);
}else if(type==2){
ll xx,yy,k;
cin>>xx>>yy>>k;
add(1,xx,yy,k);
}else{
ll xx,yy;
cin>>xx>>yy;
res[t]=ask(1,xx,yy);
t++;
}
}
for(int i=1;i<t;i++){
cout<<res[i]%q<<endl;
}
return 0;
}