#include<bits/stdc++.h>
#define maxn 110000
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
ll a[maxn],n,m,q;
struct node{
ll val;
ll la1;
ll la2;
}segtree[maxn<<2];
void pushup(ll rt)
{
segtree[rt].val=(segtree[rt*2].val+segtree[rt*2+1].val)%m;
}
void pushdown(ll rt,ll ln,ll rn)
{
ll ls=2*rt,rs=2*rt+1;
segtree[ls].val=(segtree[ls].val*segtree[rt].la1+segtree[rt].la2*ln)%m;
segtree[rs].val=(segtree[rs].val*segtree[rt].la1+segtree[rt].la2*rn)%m;
segtree[ls].la1=(segtree[ls].la1*segtree[rt].la1)%m;
segtree[rs].la1=(segtree[rs].la1*segtree[rt].la1)%m;
segtree[ls].la2=(segtree[ls].la2+segtree[rt].la2)%m;
segtree[rs].la2=(segtree[rs].la2+segtree[rt].la2)%m;
segtree[rt].la2=0;
segtree[rt].la1=1;
}
void build(ll rt,ll l,ll r)
{
segtree[rt].la1=1;
segtree[rt].la2=0;
if(l==r)
{
segtree[rt].val=a[l]%m;
return;
}
ll mid=(l+r)>>1;
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
pushup(rt);
}
void updated1(ll L,ll R,ll l,ll r,ll rt,ll val)
{
if(l>=L&&r<=R)
{
segtree[rt].val=((segtree[rt].val)*(val))%m;
segtree[rt].la1=(segtree[rt].la1*val)%m;
segtree[rt].la2=(segtree[rt].la2*val)%m;
return;
}
ll mid=(l+r)>>1;
pushdown(rt,mid-l+1,r-mid);
if(mid>=L)
updated1(L,R,l,mid,rt*2,val);
if(mid<R)
updated1(L,R,mid+1,r,rt*2+1,val);
pushup(rt);
}
void updated2(ll L,ll R,ll l,ll r,ll rt,ll val)
{
if(l>=L&&r<=R)
{
segtree[rt].val=((segtree[rt].val)+val*(r-l+1))%m;
segtree[rt].la2=(segtree[rt].la2+val)%m;
return;
}
ll mid=(l+r)>>1;
pushdown(rt,mid-l+1,r-mid);
if(mid>=L)
updated2(L,R,l,mid,rt*2,val);
if(mid<R)
updated2(L,R,mid+1,r,rt*2+1,val);
pushup(rt);
}
ll query(ll L,ll R,ll l,ll r,ll rt)
{
if(l>=L&&r<=R)
return segtree[rt].val%m;
if(r<L||l>R)
return 0;
ll mid=(l+r)>>1;
pushdown(rt,mid-l+1,r-mid);
return (query(L,R,l,mid,rt*2)%m+query(L,R,mid+1,r,rt*2+1)%m)%m;
}
int main()
{
scanf("%lld%lld%lld",&n,&q,&m);
for(ll i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
for(ll i=1;i<=q;i++)
{
ll x,y,k,mod;
scanf("%lld",&mod);
if(mod==1)
{
scanf("%lld%lld%lld",&x,&y,&k);
updated1(x,y,1,n,1,k);
}
else if(mod==2)
{
scanf("%lld%lld%lld",&x,&y,&k);
updated2(x,y,1,n,1,k);
}
else
{
scanf("%lld%lld",&x,&y);
ll ans=query(x,y,1,n,1);
printf("%lld\n",ans);
}
}
}