#include<bits/stdc++.h>
#define ll long long
#define F(i,j,n) for(ll i=j;i<=n;i++)
#define ls u<<1
#define rs u<<1|1
#define mid (tr[u].l+tr[u].r)>>1
#define mdi (l+r)>>1
using namespace std;
const int N=1e6+10;
struct tree{
ll l,r,pos,lazy,vis;
} tr[N*4];
ll n,m,a[N];
int mod;
void pushup(ll u){
tr[u].pos=tr[ls].pos+tr[rs].pos;
return ;
}
void pushdown(ll u){
ll cnt;
if(tr[u].lazy){
cnt=((tr[ls].r-tr[ls].l+1)*tr[u].lazy)%mod;
tr[ls].pos=(tr[ls].pos+cnt)%mod;
cnt=((tr[rs].r-tr[rs].l+1)*tr[u].lazy)%mod;
tr[rs].pos=(tr[rs].pos+cnt)%mod;
tr[ls].lazy=(tr[ls].lazy+tr[u].lazy)%mod;
tr[rs].lazy=(tr[rs].lazy+tr[u].lazy)%mod;
tr[u].lazy=0;
}
return ;
}
void visdown(ll u){
if(tr[u].vis!=1){
tr[ls].vis=(tr[ls].vis*tr[u].vis)%mod;
tr[rs].vis=(tr[rs].vis*tr[u].vis)%mod;
tr[ls].pos=(tr[ls].pos*tr[u].vis)%mod;
tr[rs].pos=(tr[rs].pos*tr[u].vis)%mod;
tr[u].vis=1;
}
}
void build(ll u,ll l,ll r){
tr[u].l=l;
tr[u].r=r;
tr[u].vis=1;
tr[u].lazy=0;
if(l==r){
tr[u].pos=a[l];
return ;
}
ll m=(l+r)>>1;
build(ls,l,m);
build(rs,m+1,r);
pushup(u);
return ;
}
void change(ll u,ll l,ll r,ll k){
if(l<=tr[u].l&&tr[u].r<=r){
tr[u].pos=(tr[u].pos+((tr[u].r-tr[u].l+1)*k)%mod)%mod;
tr[u].lazy=(tr[u].lazy+k)%mod;
visdown(u);
return ;
}
pushdown(u);
visdown(u);
if(l<=mid) change(ls,l,r,k);
if(mid<r) change(rs,l,r,k);
pushup(u);
return ;
}
void memery(ll u,ll l,ll r,ll k){
if(l<=tr[u].l&&tr[u].r<=r){
tr[u].pos=(tr[u].pos*k)%mod;
tr[u].vis=(tr[u].vis*k)%mod;
tr[u].lazy=(tr[u].lazy*k)%mod;
visdown(u);
return ;
}
visdown(u);
pushdown(u);
if(l<=mid) memery(ls,l,r,k);
if(mid<r) memery(rs,l,r,k);
pushup(u);
return ;
}
ll found(ll u,ll l,ll r){
if(l<=tr[u].l&&tr[u].r<=r){
return tr[u].pos;
}
pushdown(u);
visdown(u);
ll ans=0;
if(l<=mid) ans=(ans+found(ls,l,r))%mod;
if(r>mid) ans=(ans+found(rs,l,r))%mod;
return ans%mod;
}
int main(){
cin>>n>>m>>mod;
F(i,1,n){
cin>>a[i];
}
build(1,1,n);
F(i,1,m){
ll id,x,y,k;
cin>>id;
if(id==1){
cin>>x>>y>>k;
memery(1,x,y,k);
}
else if(id==2){
cin>>x>>y>>k;
change(1,x,y,k);
}
else{
cin>>x>>y;
cout<<found(1,x,y)%mod<<endl;
}
}
}