#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
typedef long long LL;
struct SegmengTree
{
LL l,r,add,mul,sum;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define add(x) tree[x].add
#define mul(x) tree[x].mul
#define sum(x) tree[x].sum
}tree[maxn*4];
LL a[maxn];
LL n,m,mod;
void build(LL p,LL l,LL r)
{
l(p)=l;r(p)=r;
if(l==r) {sum(p)=a[l]%mod;mul(p)=1%mod;return;}
LL mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
sum(p)=(sum(p*2)+sum(p*2+1))%mod;
mul(p)=mul(p*2)%mod;
}
void spread(LL p)
{
if(add(p)||mul(p)!=1)
{
sum(p*2)=( sum(p*2)*mul(p) + add(p)* (r(p*2)-l(p*2)+1) )%mod;
sum(p*2+1)=( sum(p*2+1)*mul(p)+add(p)*(r(p*2+1)-l(p*2+1)+1))%mod;
mul(p*2)=(mul(p*2)*mul(p))%mod;
mul(p*2+1)=(mul(p*2+1)*mul(p))%mod;
add(p*2)=(add(p*2)*mul(p)+add(p))%mod;
add(p*2+1)=(add(p*2+1)*mul(p)+add(p))%mod;
add(p)=0;
mul(p)=1;
}
}
//打标记的点的数据就更新区间所含的sum值
void changeadd(LL p,LL l,LL r,LL d)
{
if(l<=l(p)&&r>=r(p))
{
add(p)=(add(p)+d)%mod;
sum(p)=(sum(p)+d*(r(p)-l(p)+1) )%mod;
return;///注意return
}
spread(p);
LL mid=(l(p)+r(p))/2;
if(l<=mid) changeadd(p*2,l,r,d);
if(r>mid) changeadd(p*2+1,l,r,d);
sum(p)=( sum(p*2)+sum(p*2+1) )%mod;
}
//打标记的点的数据就更新区间所含的sum值
void changemul(LL p,LL l,LL r,LL k)
{
if(l<=l(p)&&r>=r(p))
{
add(p)=(add(p)*k)%mod;//add乘了k,这样spread下传的时候是*k后的add(p)标记,直接像区间和那样就可以了
mul(p)=(mul(p)*k)%mod;
sum(p)=(sum(p)*k)%mod;
return;//注意return
}
spread(p);
LL mid=(l(p)+r(p))/2;
if(l<=mid) changemul(p*2,l,r,k);
if(r>mid) changemul(p*2+1,l,r,k);
sum(p)=( sum(p*2)+sum(p*2+1) )%mod;
}
LL ask(LL p,LL l,LL r)
{
if(l<=l(p)&&r>=r(p)) return sum(p);
spread(p);
LL val=0;
LL mid=(l(p)+r(p))/2;
if(l<=mid) val=(val+ask(p*2,l,r))%mod;
if(r>mid) val=(val+ask(p*2+1,l,r))%mod;
return val;
}
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
cin>>n>>m>>mod;
for(LL i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
LL op,l,r,k;
while(m--)
{
cin>>op>>l>>r;
if(op==1)
{
cin>>k;
changemul(1,l,r,k);
}
else if(op==2)
{
cin>>k;
changeadd(1,l,r,k);
}
else if(op==3)
{
cout<<ask(1,l,r)<<endl;
}
}
return 0;
}