#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int P=571373;
struct node{
int l,r;long long sum,jtag,ctag;
}t[N*4];
int n,m,x,y,op;
long long a[N];
void maketag(int p,long long j,long long c){
t[p].sum=(t[p].sum*c%p+(t[p].r-t[p].l+1)*j)%P;
t[p].jtag=(t[p].jtag*c+j)%P;
t[p].ctag=(t[p].ctag*c)%P;
}
void pushup(int p){
t[p].sum=(t[p*2].sum+t[p*2+1].sum)%P;
}
void pushdown(int p){
maketag(p*2,t[p].jtag,t[p].ctag);
maketag(p*2+1,t[p].jtag,t[p].ctag);
t[p].jtag=0,t[p].ctag=1;
}
void build(int p,int l,int r){
t[p].l=l,t[p].r=r,t[p].jtag=0,t[p].ctag=1;
if(l==r){
t[p].sum=a[l];
return ;
}
int mid=(l+r)/2;
build(2*p,l,mid);
build(2*p+1,mid+1,r);
pushup(p);
}
long long query(int p,int l,int r){
if(l==t[p].l&&r==t[p].r)return t[p].sum;
pushdown(p);
int mid=t[p].l+t[p].r>>1;
if(r<=mid)
return query(p*2,l,r);
else if(l>=mid+1)
return query(p*2+1,l,r);
else{
return (query(p*2,l,mid)+query(p*2+1,mid+1,r))%P;
}
}
void update(int p,int l,int r,long long j,long long c){
if(t[p].l==l&&t[p].r==r){
maketag(p,j,c);
return ;
}
pushdown(p);
int mid=t[p].l+t[p].r>>1;
if(r<=mid)
update(p*2,l,r,j,c);
else if(l>mid)
update(p*2+1,l,r,j,c);
else{
update(p*2,l,mid,j,c);
update(p*2+1,mid+1,r,j,c);
}
pushup(p);
}
int main(){
scanf("%d%d%d",&n,&m,&P);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
build(1,1,n);
while(m--){
int l,r;long long k;
scanf("%d%d%d",&op,&l,&r);
if(op==1){
scanf("%lld",&k);update(1,l,r,0,k);
}
else if(op==2){
scanf("%lld",&k);update(1,l,r,k,1);
}
else {
printf("%lld\n",query(1,l,r));
}
}
return 0;
}