#include<bits/stdc++.h>
using namespace std;
#define int long long
int read(){
char c=getchar(); int ret=0,f=1;
while (c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while (c<='9'&&c>='0') {ret=ret*10+c-'0';c=getchar();}
return ret*f;
}
int n,m,a,x,y,mo=571373;
struct N{
int s,la,la1;
}tree[1000005];
void pushup(int u){
tree[u].s=tree[u*2].s+tree[u*2+1].s;
}
void build(int l,int r,int u){
tree[u].la1=1;
if(l==r){
tree[u].s=read();
return ;
}
int m=(l+r)/2;
build(l,m,u*2);
build(m+1,r,u*2+1);
pushup(u);
}
void pushdown(int l,int r,int u){
int m=(l+r)/2;
tree[u*2].s=(tree[u*2].s*tree[u].la1+tree[u].la*(m-l+1))%mo;
tree[u*2+1].s=(tree[u*2+1].s*tree[u].la1+tree[u].la*(r-m))%mo;
tree[u*2].la1=(tree[u*2].la1*tree[u].la1)%mo;
tree[u*2+1].la1=(tree[u*2+1].la1*tree[u].la1)%mo;
tree[u*2].la=(tree[u*2].la*tree[u].la1+tree[u].la)%mo;
tree[u*2+1].la=(tree[u*2+1].la*tree[u].la1+tree[u].la)%mo;
tree[u].la1=1;
tree[u].la=0;
}
void updata(int L,int R,int x,int l,int r,int u){
if(L<=l&&r<=R){
tree[u].s+=x*(r-l+1);
tree[u].la+=x;
return ;
}
pushdown(l,r,u);
int m=(l+r)/2;
if(L<=m) updata(L,R,x,l,m,u*2);
if(m<R) updata(L,R,x,m+1,r,u*2+1);
pushup(u);
}
void updata1(int L,int R,int x,int l,int r,int u){
if(r<L||R<l){
return ;
}
if(L<=l&&r<=R){
tree[u].s=(tree[u].s*x)%mo;
tree[u].la1=(tree[u].la1*x)%mo;
tree[u].la=(tree[u].la*x)%mo;
return ;
}
pushdown(l,r,u);
int m=(l+r)/2;
updata(L,R,x,l,m,u*2);
updata(L,R,x,m+1,r,u*2+1);
pushup(u);
}
int query(int L,int R,int l,int r,int u){
if(L<=l&&r<=R){
return tree[u].s;
}
pushdown(l,r,u);
int ans=0;
int m=(l+r)/2;
if(L<=m){
ans+=query(L,R,l,m,u*2);
}
if(m<R){
ans+=query(L,R,m+1,r,u*2+1);
}
return ans%mo;
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
cin>>n>>m>>mo;
build(1,n,1);
for(int i=1;i<=m;i++){
int a,x,y,k;
a=read();x=read();y=read();
if(a==1){
k=read();
updata1(x,y,k,1,n,1);
}
else{
if(a==2){
k=read();
updata(x,y,k,1,n,1);
}
else{
cout<<query(x,y,1,n,1)%mo<<endl;
}
}
}
return 0;
}
不知道哪里错了