#include<bits/stdc++.h>
using namespace std;
struct node{
int l,r,val,add,mul;
} t[800001];
int n,a[100001],mod,q;
int build(int id,int l,int r){
t[id].add=0,t[id].mul=1,t[id].l=l,t[id].r=r;
if(l==r) return t[id].val=a[l]%mod;
int mid=(l+r)>>1;
return t[id].val=build(id<<1,l,mid)+build(id<<1|1,mid+1,r);
}
void pushdown(int id){
t[id<<1].mul=t[id<<1].mul*t[id].mul%mod,t[id<<1|1].mul=t[id<<1|1].mul*t[id].mul%mod;
t[id].val=t[id].val*t[id].mul%mod,t[id].add=t[id].add*t[id].mul%mod,t[id].mul=1;
t[id<<1].add=(t[id<<1].add+t[id].add)%mod,t[id<<1|1].add+=(t[id].add+t[id<<1|1].add)%mod;
t[id].val=(t[id].val+t[id].add*(t[id].r-t[id].l+1))%mod,t[id].add=0;
return;
}
void add(int id,int l,int r,int c){
if(t[id].l>r or t[id].r<l) return;
if(t[id].l>=l and t[id].r<=r){
t[id].add=(t[id].add+c)%mod;
t[id].val=(t[id].val+c*(t[id].r-t[id].l+1))%mod;
return;
}
pushdown(id);
add(id<<1,l,r,c),add(id<<1|1,l,r,c);
t[id].val=(t[id<<1].val+t[id<<1|1].val)%mod;
return;
}
void mul(int id,int l,int r,int c){
if(t[id].l>r or t[id].r<l) return;
if(t[id].l>=l and t[id].r<=r){
t[id].val=t[id].val*c%mod;
t[id].mul=t[id].mul*c%mod;
t[id].add=t[id].add*c%mod;
return;
}
pushdown(id);
mul(id<<1,l,r,c),mul(id<<1|1,l,r,c);
t[id].val=(t[id<<1].val+t[id<<1|1].val)%mod;
return;
}
int query(int id,int l,int r){
if(t[id].l>r or t[id].r<l) return 0;
if(t[id].l>=l and t[id].r<=r){
return t[id].val%mod;
}
pushdown(id);
int res=(query(id<<1,l,r)+query(id<<1|1,l,r))%mod;
t[id].val=(t[id<<1].val+t[id<<1|1].val)%mod;
return res;
}
int main(){
scanf("%d%d%d",&n,&q,&mod);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,1,n);
while(q--){
int op,l,r,c;
scanf("%d%d%d",&op,&l,&r);
if(op==1){
scanf("%d",&c);
mul(1,l,r,c);
}else if(op==2){
scanf("%d",&c);
add(1,l,r,c);
}else{
printf("%d\n",query(1,l,r));
}
}
return 0;
}