#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5,N4=4e5+5;
int a[N],tree[N4],tag[N4],p,tag2[N4];
void pushup(int cur){
tree[cur]=tree[cur*2]+tree[cur*2+1];
tree[cur]%=p;
return;
}
void pushdown(int cur,int lt,int rt){
if(tag[cur]==0&&tag2[cur]==1){
return;
}
int mid=(lt+rt)/2;
tree[cur*2]=(tree[cur*2]*tag2[cur]+tag[cur]*(mid-lt+1))%p;
tree[cur*2+1]=(tree[cur*2+1]*tag2[cur]+tag[cur]*(rt-mid))%p;
tag2[cur*2]=(tag2[cur*2]*tag2[cur])%p;
tag2[cur*2+1]=(tag2[cur*2+1]*tag2[cur])%p;
tag[cur*2]=(tag[cur*2]*tag2[cur]+tag[cur])%p;
tag[cur*2+1]=(tag[cur*2+1]*tag2[cur]+tag[cur])%p;
tag2[cur]=1;
tag[cur]=0;
return;
}
void build(int cur,int lt,int rt){
if(lt==rt){
tree[cur]=a[lt];
return;
}
tag[cur]=0;
tag2[cur]=1;
int mid=(lt+rt)/2;
build(cur*2,lt,mid);
build(cur*2+1,mid+1,rt);
pushup(cur);
return;
}
int cx(int cur,int lt,int rt,int ql,int qr){
if(rt<ql||lt>qr){
return 0;
}
if(lt>=ql&&rt<=qr){
return tree[cur];
}
pushdown(cur,lt,rt);
int mid=(lt+rt)/2;
return (cx(cur*2,lt,mid,ql,qr)+cx(cur*2+1,mid+1,rt,ql,qr))%p;
}
void update(int cur,int lt,int rt,int ql,int qr,int val){
if(rt<ql||lt>qr){
return;
}
if(lt>=ql&&rt<=qr){
tag[cur]=(tag[cur]+val)%p;
tree[cur]=(tree[cur]+val*(rt-lt+1))%p;
return;
}
pushdown(cur,lt,rt);
int mid=(lt+rt)/2;
update(cur*2,lt,mid,ql,qr,val);
update(cur*2+1,mid+1,rt,ql,qr,val);
pushup(cur);
return;
}
void update2(int cur,int lt,int rt,int ql,int qr,int val){
if(rt<ql||lt>qr){
return;
}
if(lt>=ql&&rt<=qr){
tag2[cur]=(tag2[cur]*val)%p;
tag[cur]=(tag[cur]*val)%p;
tree[cur]=(tree[cur]+val*(rt-lt+1))%p;
return;
}
pushdown(cur,lt,rt);
int mid=(lt+rt)/2;
update2(cur*2,lt,mid,ql,qr,val);
update2(cur*2+1,mid+1,rt,ql,qr,val);
pushup(cur);
return;
}
signed main(){
int n,m;
cin>>n>>m>>p;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
while(m--){
int opt,lt,rt,val;
cin>>opt>>lt>>rt;
if(opt==1){
cin>>val;
update2(1,1,n,lt,rt,val);
}
else if(opt==2){
cin>>val;
update(1,1,n,lt,rt,val);
}
else{
cout<<cx(1,1,n,lt,rt)<<endl;
}
}
return 0;
}