#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+1;
int tr[N<<2],a[N];
int f[N<<2],g[N<<2];
int n,q,m;
int tp;
void push_up(int p)
{
tr[p]=(tr[p*2]+tr[p*2+1])%m;
}
void build(int p,int l,int r)
{
if(l==r) tr[p]=a[l];
else
{
int mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
push_up(p);
}
}
void push_down(int p,int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1;
tr[p*2]=(tr[p*2]*g[p])%m;
tr[p*2+1]=(tr[p*2+1]*g[p])%m;
tr[p*2]+=(mid-l+1)*f[p];
tr[p*2+1]+=(r-mid)*f[p];
tr[p*2]%=m;
tr[p*2+1]%=m;
f[p*2]+=f[p];f[p*2+1]+=f[p];
f[p*2]%=m,f[p*2+1]%=m;
g[p*2]=(g[p]*g[p*2])%m,g[p*2+1]=(g[p]*g[p*2+1])%m;
f[p]=0,g[p]=1;
}
void update_times(int p,int l,int r,int xl,int xr,int x)
{
if(xl<=l && r<=xr)
{
tr[p]=(tr[p]*x)%m;
f[p]=(f[p]*x)%m;
g[p]=(g[p]*x)%m;
return;
}
push_down(p,l,r);
int mid=(l+r)>>1;
if(xl<=mid) update_times(p*2,l,mid,xl,xr,x);
if(xr>=mid+1) update_times(p*2+1,mid+1,r,xl,xr,x);
push_up(p);
}
void update_add(int p,int l,int r,int xl,int xr,int x)
{
if(xl<=l && r<=xr)
{
tr[p]+=((r-l+1)*x)%m;
tr[p]%=m;
f[p]=(f[p]+x)%m;
return;
}
push_down(p,l,r);
int mid=(l+r)>>1;
if(xl<=mid) update_add(p*2,l,mid,xl,xr,x);
if(xr>=mid+1) update_add(p*2+1,mid+1,r,xl,xr,x);
push_up(p);
}
int query(int p,int l,int r,int xl,int xr)
{
if(xl<=l && r<=xr)
{
return tr[p];
}
int ans=0;
push_down(p,l,r);
int mid=(l+r)>>1;
if(xl<=mid) ans+=query(p*2,l,mid,xl,xr);
if(xr>=mid+1) ans+=query(p*2+1,mid+1,r,xl,xr);
return ans%m;
}
signed main()
{
ios::sync_with_stdio(false);
for(int i=1;i<=N<<2;i++) g[i]=1;
cin>>n>>q>>m;
int xl,xr,x;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
while(q--)
{
cin>>tp;
if(tp==1)
{
cin>>xl>>xr>>x;
update_times(1,1,n,xl,xr,x);
}
if(tp==2)
{
cin>>xl>>xr>>x;
update_add(1,1,n,xl,xr,x);
}
if(tp==3)
{
cin>>xl>>xr;
cout<<query(1,1,n,xl,xr)<<endl;
}
}
return 0;
}