#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 100010
int mod;
struct SegmentTree{
int v,mul,add;
}t[maxn*4];
int a[maxn];
void build(int o,int l,int r) {
t[o].mul=1;t[o].add=0;
if(l==r) {
t[o].v=a[l];
}else {
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
t[o].v=t[o>>1].v+t[o>>1|1].v;
}
t[o].v%=mod;return ;
}
void pushdown(int o,int l,int r) {
int mid=(l+r)>>1;
t[o<<1].v=(t[o<<1].v*t[o].mul+t[o].add*(mid-l+1))%mod;
t[o<<1|1].v=(t[o<<1|1].v*t[o].mul+t[o].add*(r-mid))%mod;
t[o<<1].mul=(t[o<<1].mul*t[o].mul)%mod;
t[o<<1|1].mul=(t[o<<1|1].mul*t[o].mul)%mod;
t[o<<1].add=(t[o<<1].add*t[o].mul+t[o].add)%mod;
t[o<<1|1].add=(t[o<<1|1].add*t[o].mul+t[o].add)%mod;
t[o].mul=1;
t[o].add=0;
return ;
}
void mul_update(int o,int l,int r,int al,int ar,int p) {
if(r<al||ar<l) return ;
if(l<=al&&r>=ar) {
t[o].v=(t[o].v*p)%mod;
t[o].mul=(t[o].mul*p)%mod;
t[o].add=(t[o].add*p)%mod;
return ;
}
pushdown(o,al,ar);
int mid=(al+ar)>>1;
mul_update(o<<1,l,r,al,mid,p);
mul_update(o<<1|1,l,r,mid+1,ar,p);
t[o].v=(t[o<<1].v+t[o<<1|1].v)%mod;
return ;
}
void add_update(int o,int l,int r,int al,int ar,int p) {
if(r<al||ar<l) return ;
if(l<=al&&r>=ar) {
t[o].add=(t[o].add+p)%mod;
t[o].v=(t[o].v+p*(ar-al+1))%mod;
return ;
}
pushdown(o,al,ar);
int mid=(al+ar)>>1;
add_update(o<<1,l,r,al,mid,p);
add_update(o<<1|1,l,r,mid+1,ar,p);
t[o].v=(t[o<<1].v+t[o<<1|1].v)%mod;return ;
}
int query(int o,int l,int r,int al,int ar) {
if(r<al||ar<l) return 0;
if(l<=al&&r>=ar) {
return t[o].v;
}
pushdown(o,al,ar);
int mid=(al+ar)>>1;
return (query(o<<1,l,r,al,mid)+query(o<<1|1,l,r,mid+1,ar))%mod;
}
signed main(){
int n,m;
cin>>n>>m>>mod;
for(int i=1;i<=n;i++) {
cin>>a[i];
}
build(1,1,n);
while(m--) {
int opt;
cin>>opt;
if(opt==1) {
int l,r,k;
cin>>l>>r>>k;
mul_update(1,l,r,1,n,k);
}
else if(opt==2) {
int l,r,k;
cin>>l>>r>>k;
add_update(1,l,r,1,n,k);
}
else {
int l,r;
cin>>l>>r;
cout<<query(1,l,r,1,n)<<"\n";
}
}
return 0;
}