#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=100000+5;
ll a[maxn],tr[maxn*4],tag1[maxn*4],tag2[maxn*4],n,m,p;
inline ll lc(ll rt){ return rt<<1;}
inline ll rc(ll rt){ return rt<<1|1;}
inline void pushup(ll rt){
tr[rt]=(tr[lc(rt)]+tr[rc(rt)])%p;
}
void build(ll rt,ll l,ll r){
if(l==r){
tr[rt]=a[l];
return;
}
ll mid=l+r>>1;
build(lc(rt),l,mid);
build(rc(rt),mid+1,r);
pushup(rt);
}
void pushdown(ll rt,ll l,ll r){
ll mid=l+r>>1;
tr[rc(rt)]=(tr[rc(rt)]*tag1[rt]%p+tag2[rt]*(r-mid)%p)%p;
tr[lc(rt)]=(tr[lc(rt)]*tag1[rt]%p+tag2[rt]*(mid-l+1)%p)%p;
tag2[lc(rt)]=tag2[lc(rt)]*tag1[rt]%p;tag2[rc(rt)]=tag2[rc(rt)]*tag1[rt]%p;
tag2[lc(rt)]=(tag2[lc(rt)]+tag2[rt])%p;tag2[rc(rt)]=(tag2[rc(rt)]+tag2[rt])%p;
tag1[lc(rt)]=tag1[lc(rt)]*tag1[rt]%p;tag1[rc(rt)]=(tag1[rc(rt)]*tag1[rt])%p;
tag1[rt]=1,tag2[rt]=0;
}
void update(ll rt,ll l,ll r,ll nl,ll nr,ll x,ll f){
if(nl<=l&&nr>=r){
if(f==1){
tr[rt]=(tr[rt]+(r-l+1)*x%p)%p;
tag2[rt]=(tag2[rt]+x)%p;
}
if(f==2){
tr[rt]=tr[rt]*x%p;
tag2[rt]=tag2[rt]*x%p;
tag1[rt]=tag1[rt]*x%p;
}
return;
}
ll mid=l+r>>1;
pushdown(rt,l,r);
if(nl<=mid) update(lc(rt),l,mid,nl,nr,x,f);
if(nr>mid) update(rc(rt),mid+1,r,nl,nr,x,f);
pushup(rt);
}
ll query(ll rt,ll l,ll r,ll nl,ll nr){
if(l>=nl&&r<=nr) return tr[rt];
ll mid=l+r>>1;
pushdown(rt,l,r);
ll ans=0;
if(nl<=mid) ans=(ans+query(lc(rt),l,mid,nl,nr))%p;
if(nr>mid) ans=(ans+query(rc(rt),mid+1,r,nl,nr))%p;
return ans;
}
int main(){
memset(tag1,1,sizeof(tag1));
cin>>n>>m>>p;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
for(int i=1;i<=m;i++){
ll f,l,r,x;
scanf("%lld%lld%lld",&f,&l,&r);
if(f!=3){
scanf("%lld",&x);
update(1,1,n,l,r,x,f);
}
else printf("%lld\n",query(1,1,n,l,r));
}
}