#include<bits/stdc++.h>
#define int long long
#define max(a,b) (a>b? a:b);
using namespace std;
const int N=1e5;
struct tree{
int l,r,maxn;
int num;
int add;
int chen=1;
}t[N*4];
int a[N],n,m,p;
void build(int p,int l,int r){
t[p].chen=1; t[p].add=0;
t[p].l=l; t[p].r=r;
if(l==r){
t[p].num=a[l];
return ;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
t[p].num=t[p<<1].num+t[p<<1|1].num;
return ;
}
void spread(int p){
t[p<<1].num=(t[p<<1].num*t[p].chen%p+(t[p<<1].r-t[p<<1].l+1)*t[p].add%p)%p;
t[p<<1|1].num=(t[p<<1|1].num*t[p].chen%p+(t[p<<1|1].r-t[p<<1|1].l+1)*t[p].add%p)%p;
t[p<<1].chen=t[p<<1].chen*t[p].chen%p;
t[p<<1|1].chen=t[p<<1|1].chen*t[p].chen%p;
t[p<<1].add=t[p<<1].add*t[p].chen+t[p].add;
t[p<<1|1].add=t[p<<1|1].add*t[p].chen+t[p].add;
t[p].chen=1;
t[p].add=0;
return ;
}
void update(int p,int l,int r,int k){
if(l<=t[p].l&&r>=t[p].r){
t[p].num=(t[p].num+(t[p].r-t[p].l+1)*k)%p;
t[p].add=(t[p].add+k)%p;
return ;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid) update(p<<1,l,r,k);
if(mid<r) update(p<<1|1,l,r,k);
return ;
}
void change(int p,int l,int r,int k){
if(l<=t[p].l&&r>=t[p].r){
t[p].num=t[p].num*k%p;
t[p].chen=t[p].chen*k%p;
t[p].add=t[p].add*k%p;
return ;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid) change(p<<1,l,r,k);
if(mid<r) change(p<<1|1,l,r,k);
return ;
}
int ask(int p,int l,int r){
if(l<=t[p].l&&r>=t[p].r){
return t[p].num;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
int ans=0;
if(l<=mid) ans+=ask(p<<1,l,r);
if(mid<r) ans+=ask(p<<1|1,l,r);
return ans;
}
signed main(){
std::ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>p;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i=1;i<=m;i++){
int opt,x,y,k;
cin>>opt>>x>>y;
if(opt==1){
cin>>k;
change(1,x,y,k);
}
else if(opt==2){
cin>>k;
update(1,x,y,k);
}
else{
cout<<ask(1,x,y)%p<<"\n";
}
}
return 0;
}