#include<bits/stdc++.h>
#define ll long long int
using namespace std;
const int N=1e5+7;
struct xds{
ll val,mul,add;
}tr[4*N];
ll a[N],n,mod;
void build(ll l,ll r,ll p){
tr[p].mul=1,tr[p].add=0;
if (l==r){
tr[p].val=a[l]%mod;
return ;
}
ll mid=(l+r)>>1;
build(l,mid,2*p);
build(mid+1,r,2*p+1);
tr[p].val=tr[2*p].val+tr[2*p+1].val;
tr[p].val%=mod;
return ;
}
void push(ll l,ll r,ll p){
ll mid=(l+r)>>1;
tr[2*p].val=(tr[2*p].val*tr[p].mul+tr[p].add*(l-mid+1))%mod;
tr[2*p+1].val=(tr[2*p+1].val*tr[p].mul+tr[p].add*(r-mid))%mod;
tr[2*p].mul=(tr[2*p].mul*tr[p].mul)%mod;
tr[2*p+1].mul=(tr[2*p+1].mul*tr[p].mul)%mod;
tr[2*p].add=(tr[2*p].add*tr[p].mul+tr[p].add)%mod;
tr[2*p+1].add=(tr[2*p+1].add*tr[p].mul+tr[p].add)%mod;
tr[p].add=0,tr[p].mul=1;
return ;
}
void updatemul(ll l,ll r,ll s,ll t,ll p,ll up){
if (r<s || t<l){
return ;
}
if (l<=s && t<=r){
tr[p].val=(tr[p].val*up)%mod;
tr[p].mul=(tr[p].mul*up)%mod;
tr[p].add=(tr[p].add*up)%mod;
return ;
}
push(s,t,p);
ll mid=(s+t)>>1;
updatemul(l,r,s,mid,2*p,up);
updatemul(l,r,mid+1,t,2*p+1,up);
tr[p].val=(tr[2*p].val+tr[2*p+1].val)%mod;
return ;
}
void updateadd(ll l,ll r,ll s,ll t,ll p,ll up){
if (r<s || t<l){
return ;
}
if (l<=s && t<=r){
tr[p].add=(tr[p].add+up)%mod;
tr[p].val=(tr[p].val+up*(t-s+1))%mod;
return ;
}
push(s,t,p);
ll mid=(s+t)>>1;
updateadd(l,r,s,mid,2*p,up);
updateadd(l,r,mid+1,t,2*p+1,up);
tr[p].val=(tr[2*p].val+tr[2*p+1].val)%mod;
return ;
}
ll query(ll l,ll r,ll s,ll t,ll p){
if (r<s || t<l){
return 0;
}
if (l<=s && t<=r){
return tr[p].val;
}
push(s,t,p);
ll mid=(s+t)>>1;
return (query(l,r,s,mid,2*p)+query(l,r,mid+1,t,2*p+1))%mod;
}
int main()
{
ll q;
cin>>n>>q>>mod;
for (int i=1;i<=n;i++){
cin>>a[i];
}
build(1,n,1);
while (q--){
ll op,x,y,k;
cin>>op;
if (op==1){
cin>>x>>y>>k;
updatemul(x,y,1,n,1,k);
}
if (op==2){
cin>>x>>y>>k;
updateadd(x,y,1,n,1,k);
}
if (op==3){
cin>>x>>y;
cout<<query(x,y,1,n,1)<<endl;
}
}
return 0;
}