#include<bits/stdc++.h>
#define Access using
#define Code namespace
#define Talker std
Access Code Talker;
#define int long long
const int maxn=500010;
int tr[maxn<<2],tag[maxn<<2],lz[maxn<<2];
int mod;
inline int r(){
int x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<3)+(x<<1)+c-'0';c=getchar();}return x*f;
}
void upto(int p){
tr[p]=(tr[p<<1]+tr[p<<1|1])%mod;
}
void build(int s,int t,int p){
lz[p]=1;
if(s==t)tr[p]=r();
else{
int m=(s+t)>>1;
build(s,m,p<<1);
build(m+1,t,p<<1|1);
upto(p);
}
}
void push(int s,int t,int p){
int m=(s+t)>>1;
lz[p<<1]=(lz[p<<1]*lz[p])%mod;
lz[p<<1|1]=(lz[p<<1|1]*lz[p])%mod;
tag[p<<1]=(tag[p<<1]*lz[p])%mod;
tag[p<<1|1]=(tag[p<<1|1]*lz[p])%mod;
tag[p<<1]=(tag[p<<1]+tag[p])%mod;
tag[p<<1|1]=(tag[p<<1|1]+tag[p])%mod;
tr[p<<1]=(tr[p<<1]*lz[p])%mod;
tr[p<<1|1]=(tr[p<<1|1]*lz[p])%mod;
tr[p<<1]=(tr[p<<1]+(m-s+1)*tag[p])%mod;
tr[p<<1|1]=(tr[p<<1|1]+(t-m)*tag[p])%mod;
tag[p]=0;lz[p]=1;
}
void update1(int l,int r,int c,int s,int t,int p){
if(l<=s&&t<=r){
tr[p]=(tr[p]+(t-s+1)*c)%mod;
tag[p]=(tag[p]+c)%mod;
return;
}else{
int m=(s+t)>>1;
if(tag[p]&&s!=t)push(s,t,p);
if(l<=m)update1(l,r,c,s,m,p<<1);
if(r>m)update1(l,r,c,m+1,t,p<<1|1);
upto(p);
}
}
void update2(int l,int r,int c,int s,int t,int p){
if(l<=s&&t<=r){
tr[p]=(tr[p]*c)%mod;
tag[p]=(tag[p]*c)%mod;
lz[p]=(lz[p]*c)%mod;
return;
}else{
int m=(s+t)>>1;
if(tag[p]&&s!=t)push(s,t,p);
if(l<=m)update2(l,r,c,s,m,p<<1);
if(r>m)update2(l,r,c,m+1,t,p<<1|1);
upto(p);
}
}
int query(int l,int r,int s,int t,int p){
if(l<=s&&t<=r)
return tr[p];
int m=(s+t)>>1,res=0;
if(tag[p])push(s,t,p);
if(l<=m)res=(res+query(l,r,s,m,p<<1))%mod;
if(r>m)res=(res+query(l,r,m+1,t,p<<1|1))%mod;
return res;
}
signed main(){
int n=r(),m=r();mod=r();
build(1,n,1);
while(m--){
int op=r(),x=r(),y=r();
if(op==1){
int w=r();
update2(x,y,w,1,n,1);
}
else if(op==2){
int w=r();
update1(x,y,w,1,n,1);
}
else cout<<query(x,y,1,n,1)<<endl;
}
return 0;
}