#include<bits/stdc++.h>
using namespace std;
//#define int long long
int n,m,a[100005],ls,rs;
long long k,q,mod;
struct tree{
int l,r,mid;
long long all,add,res;
}tr[400005];
void bulid(int p,int left,int right){
tr[p].res=1;
tr[p].add=0;
tr[p].l=left;
tr[p].r=right;
tr[p].mid=(tr[p].l+tr[p].r)/2;
if(left==right){
tr[p].all=a[left];
return;
}
bulid(p*2,left,(left+right)/2);
bulid(p*2+1,(left+right)/2+1,right);
tr[p].all=(tr[p*2].all+tr[p*2+1].all)%mod;
}
void lazy(int p){
tr[p*2].all=tr[p*2].all*tr[p].res+tr[p].add*(tr[p*2].r-tr[p*2].l+1);
tr[p*2].all%=mod;
tr[p*2+1].all=tr[p*2+1].all*tr[p].res+tr[p].add*(tr[p*2+1].r-tr[p*2+1].l+1);
tr[p*2+1].all%=mod;
tr[p*2].res=tr[p*2].res*tr[p].res;
tr[p*2].res%=mod;
tr[p*2+1].res=tr[p*2+1].res*tr[p].res;
tr[p*2+1].res%=mod;
tr[p*2].add=tr[p*2].add*tr[p].res+tr[p].add;
tr[p*2].add%=mod;
tr[p*2+1].add=tr[p*2+1].add*tr[p].res+tr[p].add;
tr[p*2+1].add%=mod;
tr[p].add=0;
tr[p].res=1;
}
void change(int p,int x,int y,long long z){
if(x<=tr[p].l&&y>=tr[p].r){
tr[p].all=tr[p].all+z*(tr[p].r-tr[p].l+1);
tr[p].all%=mod;
tr[p].add+=z;
tr[p].add%=mod;
return;
}
lazy(p);
if(x<=tr[p].mid) change(p*2,x,y,z);
if(y>tr[p].mid) change(p*2+1,x,y,z);
tr[p].all=(tr[p*2].all+tr[p*2+1].all)%mod;
}void change2(int p,int x,int y,long long z){
if(x<=tr[p].l&&y>=tr[p].r){
tr[p].all=tr[p].all*z;
tr[p].all%=mod;
tr[p].add*=z;
tr[p].add%=mod;
tr[p].res*=z;
tr[p].res%=mod;
return;
}
lazy(p);
if(x<=tr[p].mid) change(p*2,x,y,z);
if(y>tr[p].mid) change(p*2+1,x,y,z);
tr[p].all=(tr[p*2].all+tr[p*2+1].all)%mod;
}
long long find(int p,int x,int y){
if(x<=tr[p].l&&y>=tr[p].r) return tr[p].all;
lazy(p);
long long ans=0;
if(x<=tr[p].mid) ans+=find(p*2,x,y);
if(y>tr[p].mid) ans+=find(p*2+1,x,y);
return ans%mod;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m>>mod;
for(int i=1;i<=n;i++) cin>>a[i];
bulid(1,1,n);
for(int i=1;i<=m;i++){
cin>>q;
if(q==1){
cin>>ls>>rs>>k;
change2(1,ls,rs,k);
}
if(q==2){
cin>>ls>>rs>>k;
change(1,ls,rs,k);
}
else{
cin>>ls>>rs;
cout<<find(1,ls,rs)<<'\n';
}
}
}
0pts