#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int mod;
struct node{
int l,r;
ll mu,lazy,sum;
}z[4*N+20];
int a[N];
void lazzy(int p){
z[p*2].sum=(ll)(z[p].mu*z[p*2].sum+((z[p*2].r-z[p*2].l+1)*z[p].lazy)%mod)%mod;
z[p*2+1].sum=(ll)(z[p].mu*z[p*2+1].sum+(z[p].lazy*(z[p*2+1].r-z[p*2+1].l+1))%mod)%mod;//lazy已经乘过mu啦
z[p*2].mu=(ll)(z[p*2].mu*z[p].mu)%mod;
z[p*2+1].mu=(ll)(z[p*2+1].mu*z[p].mu)%mod;
z[p*2].lazy=(ll)(z[p*2].lazy*z[p].mu+z[p].lazy)%mod;
z[p*2+1].lazy=(ll)(z[p*2+1].lazy*z[p].mu+z[p].lazy)%mod;
z[p].mu=1,z[p].lazy=0;
}
void build(int l,int r,int p){
z[p].l=l;
z[p].r=r;
z[p].mu=1;
if(l==r){
z[p].sum=a[l]%mod;
return ;
}
int mid=r+l>>1;
build(l,mid,p*2);
build(mid+1,r,p*2+1);
z[p].sum=(z[p*2].sum+z[p*2+1].sum)%mod;
}
void chan1(int l,int r,int p,int k){
if(l<=z[p].l&&r>=z[p].r){
z[p].lazy=(z[p].lazy+k)%mod;
z[p].sum=(ll)(z[p].sum+k*(z[p].r-z[p].l+1))%mod;
return ;
}
lazzy(p);
z[p].sum=(z[p*2].sum+z[p*2+1].sum)%mod;
ll mid=z[p].l+z[p].r>>1;
if(l<=mid) {
chan1(l,r,p*2,k);
}
if(r>mid){
chan1(l,r,p*2+1,k);
}
z[p].sum=(z[p*2].sum+z[p*2+1].sum)%mod;
}
void chan2(int l,int r,int p,int k){
if(z[p].l>=l&&z[p].r<=r){
z[p].lazy=(z[p].lazy*k)%mod;
z[p].mu=(z[p].mu*k)%k;
z[p].sum=(z[p].sum*k)%mod;
return ;
}
lazzy(p);
ll mid=z[p].l+z[p].r>>1;
z[p].sum=z[p*2].sum+z[p*2+1].sum;
if(l<=mid) {
chan2(l,r,p*2,k);
}
if(r>mid){
chan2(l,r,p*2+1,k);
}
z[p].sum=(z[p*2].sum+z[p*2+1].sum)%mod;
}
ll find(int p,int l,int r){
if(z[p].l>=l&&z[p].r<=r){
return z[p].sum;
}
lazzy(p);
ll val=0;
int mid=(z[p].l+z[p].r)>>1;
if(l<=mid)val=(val+find(p*2,l,r))%mod;
if(mid<r)val=(val+find(p*2+1,l,r))%mod;
return val;
}
int main(){
int n,t,m;
scanf("%d%d%d",&n,&t,&m);
mod=m;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,n,1);
for(int i=1;i<=t;i++){
int opt,x,y;
scanf("%d",&opt);
if(opt==1){
int k;
scanf("%d%d%d",&x,&y,&k);
chan2(x,y,1,k);
}
if(opt==2){
int k;
scanf("%d%d%d",&x,&y,&k);
chan1(x,y,1,k);
}
if(opt==3){
scanf("%d%d",&x,&y);
printf("%lld\n",find(1,x,y)%mod);
}
}
}
全wa求调