rt
#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct node{
int l,r;
ll dat,atag,mtag;
#define l(x) t[x].l
#define r(x) t[x].r
}t[4*100000+5];
int n,q,a[100005]={0};
ll m;
void build(int x,int l,int r){
t[x].l=l,t[x].r=r,t[x].mtag=1,t[x].atag=0;
if(l==r){
t[x].dat=a[l]%m;
return;
}
int mid=(l+r)>>1;
build(2*x,l,mid);
build(2*x+1,mid+1,r);
t[x].dat=(t[2*x].dat+t[2*x+1].dat)%m;
return;
}
void spr(int x){
int ls=2*x;
t[ls].dat=((t[ls].dat*t[x].mtag)%m+(t[x].atag*(r(ls)-l(ls)+1))%m)%m;
t[ls].atag=(t[ls].atag*t[x].mtag)%m+t[x].atag,t[ls].mtag*=t[x].mtag;
t[ls].atag%=m,t[ls].mtag%=m;
t[ls+1].dat=((t[ls+1].dat*t[x].mtag)%m+(t[x].atag*(r(ls+1)-l(ls+1)+1))%m)%m;
t[ls+1].atag=(t[ls+1].atag*t[x].mtag)%m+t[x].atag,t[ls+1].mtag*=t[x].mtag;
t[ls+1].atag%=m,t[ls+1].atag%=m;
t[x].atag=0,t[x].mtag=1;
return;
}
void add(int x,int l,int r,ll k){
if(l(x)>=l&&r(x)<=r){
t[x].dat+=k*(r(x)-l(x)+1);
t[x].dat%=m;
t[x].atag+=k;
t[x].atag%=m;
return;
}
if(t[x].atag!=0||t[x].mtag!=1)spr(x);
int mid=(l(x)+r(x))>>1;
if(mid>=l) add(2*x,l,r,k);
if(mid+1<=r) add(2*x+1,l,r,k);
t[x].dat=(t[2*x].dat+t[2*x+1].dat)%m;
return;
}
void mult(int x,int l,int r,ll k){
if(l(x)>=l&&r(x)<=r){
t[x].mtag*=k;
t[x].mtag%=m;
t[x].atag*=k;
t[x].atag%=m;
t[x].dat=(t[x].dat*k)%m;
return;
}
if(t[x].atag!=0||t[x].mtag!=1)spr(x);
int mid=(l(x)+r(x))>>1;
if(mid>=l) mult(2*x,l,r,k);
if(mid+1<=r) mult(2*x+1,l,r,k);
t[x].dat=(t[2*x].dat+t[2*x+1].dat)%m;
return;
}
ll ask(int x,int l,int r){
if(l(x)>=l&&r(x)<=r) return t[x].dat%m;
if(t[x].atag!=0||t[x].mtag!=1)spr(x);
ll sum=0;
int mid=(l(x)+r(x))>>1;
if(mid>=l) sum+=ask(2*x,l,r);
sum%=m;
if(mid<r) sum+=ask(2*x+1,l,r);
sum%=m;
return sum;
}
int main(){
cin>>n>>q>>m;;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
int op,l,r;
ll k;
while(q--){
scanf("%d%d%d",&op,&l,&r);
if(op==2){
scanf("%lld",&k);
add(1,l,r,k);
}
else if(op==1){
scanf("%lld",&k);
mult(1,l,r,k);
}
else {
printf("%lld\n",ask(1,l,r));
}
}
return 0;
}