#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000+5;
long long sum[maxn*4],add[maxn*4],mul[maxn*4],a[maxn],n,m,p;
void pushup(int x) {sum[x] = (sum[x*2]+sum[x*2+1])%p;}
void pushdown(int x,int ln,int rn)
{
if(!add[x]) return;
sum[x*2] = (sum[x*2]*mul[x]+ln*add[x])%p;
sum[x*2+1] = (sum[x*2+1]*mul[x]+rn*add[x])%p;
mul[x*2] = (mul[x*2]*mul[x])%p;
mul[x*2+1] = (mul[x*2+1]*mul[x])%p;
add[x*2] = (add[x*2]*mul[x]+add[x])%p;
add[x*2+1] = (add[x*2+1]*mul[x]+add[x])%p;
add[x] = 0;mul[x] = 1;
}
void build(long long l,long long r,long long x)
{
add[x] = 0;mul[x] = 1;
if(l == r) {sum[x] = a[l];return;}
long long mid = (l+r)/2;
build(l,mid,x*2);
build(mid+1,r,x*2+1);
pushup(x);
}
void update(long long l,long long r,long long d,long long lnow,long long rnow,long long x)
{
if(l <= lnow && rnow <= r)
{
sum[x] = (sum[x]+d*(rnow-lnow+1))%p;
add[x] = (add[x]+d)%p;
}
else
{
long long mid = (lnow+rnow)/2;
pushdown(x,mid-lnow+1,rnow-mid);
if(l <= mid) update(l,r,d,lnow,mid,x*2);
if(mid < r) update(l,r,d,mid+1,rnow,x*2+1);
pushup(x);
}
}
void update2(long long l,long long r,long long e,long long lnow,long long rnow,long long x)
{
if(l <= lnow && rnow <= r)
{
sum[x] = (sum[x]*e)%p;
add[x] = (add[x]*e)%p;
mul[x] = (mul[x]*e)%p;
}
else
{
long long mid = (lnow+rnow)/2;
pushdown(x,mid-lnow+1,rnow-mid);
if(l <= mid) update2(l,r,e,lnow,mid,x*2);
if(mid < r) update2(l,r,e,mid+1,rnow,x*2+1);
pushup(x);
}
}
long long query(long long l,long long r,long long lnow,long long rnow,long long x)
{
if(l <= lnow && rnow <= r) return sum[x];
else
{
long long mid = (lnow+rnow)/2;
pushdown(x,mid-lnow+1,rnow-mid);
long long tot = 0;
if(l <= mid) tot += query(l,r,lnow,mid,x*2);
if(mid < r) tot += query(l,r,mid+1,rnow,x*2+1);
return tot%p;
}
}
int main(int argc,char *argv[])
{
//freopen("2.in","r",stdin);
//freopen("2.ans","w",stdout);
scanf("%lld%lld%lld",&n,&m,&p);
for(long long i = 1;i <= n;++i) scanf("%lld",&a[i]);
build(1,n,1);
while(m--)
{
long long opt;scanf("%lld",&opt);
switch(opt)
{
case 1:
long long xo,yo,ko;
scanf("%lld%lld%lld",&xo,&yo,&ko);
update2(xo,yo,ko,1,n,1);
break;
case 2:
long long x0,y0,k0;
scanf("%lld%lld%lld",&x0,&y0,&k0);
update(x0,y0,k0,1,n,1);
break;
case 3:
long long x1,y1;
scanf("%lld%lld",&x1,&y1);
printf("%lld\n",query(x1,y1,1,n,1)%p);
break;
}
}
return 0;
}