#include<bits/stdc++.h>
using namespace std;
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
int n,q,m,a[100005];
int f,x,y,k;
int tre[400005],lazy_one[400005],lazy_two[400005];
void push_up(int f){
tre[f]=(tre[ls(f)]+tre[rs(f)])%m;
}
void push_down(int f,int l,int r){
int mid=(l+r)>>1;
lazy_one[ls(f)]=lazy_one[ls(f)]*lazy_one[f];
lazy_one[rs(f)]=lazy_one[rs(f)]*lazy_one[f];
lazy_two[ls(f)]=lazy_two[ls(f)]*lazy_one[f]+lazy_two[f];
lazy_two[rs(f)]=lazy_two[rs(f)]*lazy_one[f]+lazy_two[f];
tre[ls(f)]=tre[ls(f)]*lazy_one[f]+lazy_two[f]*(mid-l+1);
tre[rs(f)]=tre[rs(f)]*lazy_one[f]+lazy_two[f]*(r-mid);
lazy_one[f]=lazy_two[f]=0;
}
void build(int f,int l,int r){
lazy_one[f]=lazy_two[f]=0;
if(l==r){
tre[f]=a[l];
return ;
}
int mid=(l+r)>>1;
build(ls(f),l,mid);
build(rs(f),mid+1,r);
push_up(f);
}
void pus(int f,int l,int r,int x,int y,int k){
if(x<=l&&y>=r){
tre[f]+=k;
lazy_two[f]+=k;
return ;
}
int mid=(l+r)>>1;
if(x<=mid) pus(ls(f),l,mid,x,y,k);
if(y>mid) pus(rs(f),mid+1,r,x,y,k);
push_up(f);
}
void mul(int f,int l,int r,int x,int y,int k){
if(x<=l&&y>=r){
tre[f]*=k;
lazy_one[f]*=k;
lazy_two[f]*=k;
return ;
}
int mid=(l+r)>>1;
if(x<=mid) mul(ls(f),l,mid,x,y,k);
if(y>mid) mul(rs(f),mid+1,r,x,y,k);
push_up(f);
}
int query(int f,int l,int r,int x,int y){
if(x<=l&&y>=r){
return tre[f];
}
int mid=(l+r)>>1;int ans=0;
push_down(f,l,r);
if(x<=mid) ans=(ans+query(ls(f),l,mid,x,y))%m;
if(y>mid) ans=(ans+query(rs(f),mid+1,r,x,y))%m;
return ans%m;
}
int main(){
cin >> n >> q >> m;
for(int i=1;i<=n;i++){
cin >> a[i];
}
build(1,1,n);
for(int i=1;i<=q;i++){
cin >> f;
if(f==1){
cin >> x >> y >> k;
mul(1,1,n,x,y,k);
}
else if(f==2){
cin >> x >> y >> k;
pus(1,1,n,x,y,k);
}
else if(f==3){
cin >> x >> y;
cout << query(1,1,n,x,y)%m << endl;
}
}
return 0;
}