#include<iostream>
using namespace std;
int n,q,temp,x,y;
long long k,m,a[100001];
struct Tree{
long long d,zm,za;
}t[400000];
void build(int p,int l,int r){
t[p].za=0;
t[p].zm=1;
if(l==r){
t[p].d=a[l]%m;
return;
}
int mid=(l+r)>>1,ls=p<<1,rs=ls|1;
build(ls,l,mid);
build(rs,mid+1,r);
t[p].d=(t[ls].d+t[rs].d)%m;
return;
}
inline void push_down(int p,int l,int r){
int mid=(l+r)>>1,ls=p<<1,rs=ls|1;
t[ls].d=(t[ls].d*t[p].zm+(mid-l+1)*t[p].za)%m;
t[rs].d=(t[rs].d*t[p].zm+(r-mid)*t[p].za)%m;
t[ls].za=(t[ls].za*t[p].zm+t[p].za)%m;
t[rs].za=(t[rs].za*t[p].zm+t[p].za)%m;
t[ls].zm=(t[ls].zm*t[ls].zm)%m;
t[rs].zm=(t[rs].zm*t[rs].zm)%m;
t[p].za=0;
t[p].zm=1;
return;
}
void multiply(int p,int l,int r,int ql,int qr){
if(l==ql && r==qr){
t[p].d=(t[p].d*k)%m;
t[p].za=(t[p].za*k)%m;
t[p].zm=(t[p].zm*k)%m;
return;
}
push_down(p,ql,qr);
int mid=(ql+qr)>>1,ls=p<<1,rs=ls|1;
if(r<=mid) multiply(ls,l,r,ql,mid);
else if(l>mid) multiply(rs,l,r,mid+1,qr);
else multiply(ls,l,mid,ql,mid),multiply(rs,mid+1,r,mid+1,qr);
t[p].d=(t[ls].d+t[rs].d)%m;
return;
}
void addition(int p,int l,int r,int ql,int qr){
if(l==ql && r==qr){
t[p].d=(t[p].d+k*(r-l+1))%m;
t[p].za=(t[p].za+k)%m;
return;
}
push_down(p,ql,qr);
int mid=(ql+qr)>>1,ls=p<<1,rs=ls|1;
if(r<=mid) addition(ls,l,r,ql,mid);
else if(l>mid) addition(rs,l,r,mid+1,qr);
else addition(ls,l,mid,ql,mid),addition(rs,mid+1,r,mid+1,qr);
t[p].d=(t[ls].d+t[rs].d)%m;
return;
}
long long query(int p,int l,int r,int ql,int qr){
if(r<ql || l>qr) return 0;
if(l<=qr && r>=qr) return t[p].d;
push_down(p,ql,qr);
int m=(ql+qr)>>1;
return (query(p<<1,l,r,ql,m)+query((p<<1)|1,l,r,m+1,qr))%m;
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>q>>m;
for(int i=1;i<=n;++i) cin>>a[i];
build(1,1,n);
while(q--){
cin>>temp>>x>>y;
switch(temp){
case 1:
cin>>k;
k-=(k/m)*m;
multiply(1,x,y,1,n);
break;
case 2:
cin>>k;
k-=(k/m)*m;
addition(1,x,y,1,n);
break;
default:
cout<<query(1,x,y,1,n)<<endl;
break;
}
}
return 0;
}