#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
long long a[N],tree[N<<2],tag[N<<2];
long long ls(long long p){
return p<<1;
}
long long rs(long long p){
return p<<1|1;
}
void push_up(long long p){
tree[p]=tree[ls(p)]+tree[rs(p)];
}
void push_up1(long long p){
tree[p]=tree[ls(p)]*tree[rs(p)];
}
void build(long long p,long long pl,long long pr){
tag[p]=0;
if(pl==pr){
tree[p]=a[pl];
return;
}
long long mid=(pl+pr)>>1;
build(ls(p),pl,mid);
build(rs(p),mid+1,pr);
push_up(p);
}
void addtag(long long p,long long pl,long long pr,long long d){
tag[p]+=d;
tree[p]+=d*(pr-pl+1);
}
void push_down(long long p,long long pl,long long pr){
if(tag[p]){
long long mid=(pl+pr)>>1;
addtag(ls(p),pl,mid,tag[p]);
addtag(rs(p),mid+1,pr,tag[p]);
tag[p]=0;
}
}
void update(long long L,long long R,long long p,long long pl,long long pr,long long d){
if(L<=pl&&pr<=R){
addtag(p,pl,pr,d);
return;
}
push_down(p,pl,pr);
long long mid=(pl+pr)>>1;
if(L<=mid) update(L,R,ls(p),pl,mid,d);
if(R>mid) update(L,R,rs(p),mid+1,pr,d);
push_up(p);
}
void update1(long long L,long long R,long long p,long long pl,long long pr,long long d){
if(L<=pl&&pr<=R){
addtag(p,pl,pr,d);
return;
}
push_down(p,pl,pr);
long long mid=(pl+pr)>>1;
if(L<=mid) update1(L,R,ls(p),pl,mid,d);
if(R>mid) update1(L,R,rs(p),mid+1,pr,d);
push_up1(p);
}
long long query(long long L,long long R,long long p,long long pl,long long pr){
if(L<=pl&&pr<=R) return tree[p];
push_down(p,pl,pr);
long long res=0;
long long mid=(pl+pr)>>1;
if(L<=mid) res+=query(L,R,ls(p),pl,mid);
if(R>mid) res+=query(L,R,rs(p),mid+1,pr);
return res;
}
int main(){
long long n,m,b;
cin>>n>>m>>b;
for(long long i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
while(m--){
long long q,L,R,d;
cin>>q;
if(q==1){
cin>>L>>R>>d;
update1(L,R,1,1,n,d);
}
else if(q==2){
cin>>L>>R>>d;
update(L,R,1,1,n,d);
}
else{
cin>>L>>R;
cout<<query(L,R,1,1,n)%b<<endl;
}
}
return 0;
}