#include<cstdio>
#define ls u<<1
#define rs u<<1|1
using namespace std;
int p,n,m,t[100005*4],a[100005],lazm[100005*4],lazp[100005*4];//t是线段树数组 a是线段树要维护的数组 lazm是乘法标记 lazp是加法标记
void mat(int u){//维护父节点u
t[u]=((t[ls]%p)+(t[rs]%p))%p;
return;
}
void bud(int u,int L,int R){//建树
if(L==R){
lazm[u]=1;//顺便把乘法标记初始化
t[u]=a[L];
return;
}
int mid=(L+R)>>1;
bud(ls,L,mid);
bud(rs,mid+1,R);
mat(u);
lazm[u]=1;//顺便把乘法标记给初始化
return;
}
void pushdown(int u,int L,int R){//下传lazy标记
if(lazm[u]!=1){//*先下传乘法标记,同时把子树的加法和乘法标记都维护了
int k=lazm[u]%p;
lazm[u]=1;
t[ls]=((t[ls]%p)*(k))%p;
t[rs]=((t[rs]%p)*(k))%p;
lazp[ls]*=k%p;//顺便把子树的加法标记维护了
lazp[rs]*=k%p;
lazm[ls]*=k%p;
lazm[rs]*=k%p;
}
if(lazp[u]!=0){//+
int k=lazp[u],mid=(L+R)>>1;
lazp[u]=0;
t[ls]=((t[ls]%p)+(mid-L+1)*k%p)%p;
t[rs]=((t[rs]%p)+(R-mid)*k%p)%p;
lazp[ls]%=p;lazp[ls]+=k;
lazp[rs]%=p;lazp[rs]+=k;
}
return;
}
bool in(int l,int r,int L,int R){//l LR r 这个函数用来判断线段树是不是在维护区间内
return l<=L&&R<=r;
}
bool out(int l,int r,int L,int R){//LR lr lr LR 这个函数判断线段树和维护的区间有没有交集
return R<l||r<L;
}
void pls(int u,int l,int r,int L,int R,int k){//维护加操作的函数
if(in(l,r,L,R)){
t[u]=((t[u]%p)+((R-L+1)*k)%p)%p;
lazp[u]+=k;
return;
}
pushdown(u,L,R);
int mid=(L+R)>>1;
if(!out(l,r,L,mid)){
pls(ls,l,r,L,mid,k);
}
if(!out(l,r,mid+1,R)){
pls(rs,l,r,mid+1,R,k);
}
mat(u);
return;
}
void mut(int u,int l,int r,int L,int R,int k){//维护乘法的函数
if(in(l,r,L,R)){
t[u]=((t[u]%p)*(k%p))%p;
lazp[u]*=k;
lazm[u]*=k;
return;
}
pushdown(u,L,R);
int mid=(L+R)>>1;
if(!out(l,r,L,mid)){
mut(ls,l,r,L,mid,k);
}
if(!out(l,r,mid+1,R)){
mut(rs,l,r,mid+1,R,k);
}
mat(u);
return;
}
int fid(int u,int l,int r,int L,int R){//查询区间和
if(in(l,r,L,R))return t[u]%p;
pushdown(u,L,R);
int tep=0,mid=(L+R)>>1;
if(!out(l,r,L,mid))tep+=(fid(ls,l,r,L,mid));
if(!out(l,r,mid+1,R))tep=((tep%p)+(fid(rs,l,r,mid+1,R)%p))%p;
return tep;
}
int main(){
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
bud(1,1,n);
for(int i=m;i;i--){
int opt,x,y,k;
scanf("%d%d%d",&opt,&x,&y);
if(opt==1){//*
scanf("%d",&k);
mut(1,x,y,1,n,k);
}
else if(opt==2){//+
scanf("%d",&k);
pls(1,x,y,1,n,k);
}
else{//return sum[x,y]%p
printf("%d\n",fid(1,x,y,1,n)%p);
}
}
// for(int i=1;i<=15;i++)printf("%d ",t[i]);
return 0;
}