RT
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define rd read()
typedef long long int ll;
using namespace std;
const ll MAXN=100002;
inline ll read(){
ll x=0;
char g=getchar();
bool f=true;
for(;!isdigit(g);g=getchar())if(g=='-')f=!f;
for(;isdigit(g);g=getchar())x=(x<<1)+(x<<3)+(g^48);
return f?x:-x;
}
ll n,m,p;
ll sum[MAXN<<2];
ll add[MAXN<<2];
ll mut[MAXN<<2];
ll a[MAXN];
ll tree_build(int l,int r,int rt){
add[rt]=0;
mut[rt]=1;
if(l==r)return sum[rt]=a[l];
ll mid=(l+r)>>1;
return sum[rt]=(tree_build(l,mid,rt<<1)
+tree_build(mid+1,r,rt<<1|1))%p;
}
void push_down(ll l,ll r,ll rt){
ll mid=(l+r)>>1;
if(mut[rt]!=1){
sum[rt<<1]=sum[rt<<1]*mut[rt]%p;
sum[rt<<1|1]=sum[rt<<1|1]*mut[rt]%p;
mut[rt<<1]=mut[rt<<1]*mut[rt]%p;
mut[rt<<1|1]=mut[rt<<1|1]*mut[rt]%p;
mut[rt]=1;
}
if(add[rt]!=0){
sum[rt<<1]=(sum[rt<<1]+add[rt]*(mid-l+1))%p;
sum[rt<<1|1]=(sum[rt<<1|1]+add[rt]*(r-mid))%p;
add[rt<<1]=(add[rt<<1]+add[rt])%p;
add[rt<<1|1]=(add[rt<<1|1]+add[rt])%p;
add[rt]=0;
}
sum[rt<<1]=(sum[rt<<1]+add[rt]*(mid-l+1))%p;
sum[rt<<1|1]=(sum[rt<<1|1]+add[rt]*(r-mid))%p;
add[rt<<1]=(add[rt<<1]+add[rt])%p;
add[rt<<1|1]=(add[rt<<1|1]+add[rt])%p;
add[rt]=0;
return;
}
void ADD(ll L,ll R,ll l,ll r,ll rt,ll k){
if(L<=l&&r<=R){
add[rt]=(add[rt]+k)%p;
sum[rt]=(sum[rt]+(r-l+1)*k)%p;
return;
}
ll mid=(r+l)>>1;
push_down(l,r,rt);
if(L<=mid)ADD(L,R,l,mid,rt<<1,k);
if(mid+1<=R)ADD(L,R,mid+1,r,rt<<1|1,k);
sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
return;
}
ll SUM(ll L,ll R,ll l,ll r,ll rt){
if(L<=l&&r<=R)return sum[rt];
ll res=0;
ll mid=(r+l)>>1;
push_down(l,r,rt);
if(L<=mid)res=(res+SUM(L,R,l,mid,rt<<1))%p;
if(mid+1<=R)res=(res+SUM(L,R,mid+1,r,rt<<1|1))%p;
return res;
}
void MUT(ll L,ll R,ll l,ll r,ll rt,ll k){
if(L<=l&&r<=R){
mut[rt]=(mut[rt]*k)%p;
add[rt]=(add[rt]*k)%p;
sum[rt]=(sum[rt]*k)%p;
return;
}
ll mid=(r+l)>>1;
push_down(l,r,rt);
if(L<=mid)MUT(L,R,l,mid,rt<<1,k);
if(mid+1<=R)MUT(L,R,mid+1,r,rt<<1|1,k);
sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;
return;
}
int main(){
freopen("P3373_2.in","r",stdin);
freopen("res.txt","w",stdout);
n=rd,m=rd,p=rd;
for(int i=1;i<=n;i++)a[i]=rd%p;
tree_build(1,n,1);
for(int i=1;i<=m;i++){
ll x=rd,L=rd,R=rd;
if(x==1){
MUT(L,R,1,n,1,rd%p);
}else if(x==2){
ADD(L,R,1,n,1,rd%p);
}else if(x==3){
printf("%lld\n",SUM(L,R,1,n,1)%p);
}
}
return 0;
}