#include<bits/stdc++.h>
#define p1 p<<1
#define p2 (p<<1)+1
using namespace std;
typedef long long ll;
ll n,m,a[110000],mm;
const int N=110000;
ll tree[N<<2+2];
ll tap[N<<2+2],tap1[N<<2+2];
void push_up(ll p) {
tree[p]=tree[p1]+tree[p2];
return;
}
void built(ll p,ll lp,ll rp) {
tap[p]=0;
if(lp==rp) {
tree[p]=a[lp];
return;
}
ll mid=(lp+rp)/2;
built(p1,lp,mid);
built(p2,mid+1,rp);
push_up(p);
return;
}
void addtag(ll p,ll pl,ll pr,ll ta) {
tap[p]=(tap[p]+ta)%mm;
tree[p]=(tree[p]+(1+pr-pl)*ta)%mm;
return;
}
void addtag1(ll p,ll pl,ll pr,ll ta) {
tap1[p]=(tap1[p]+ta)%mm;
tree[p]=(tree[p]*ta)%mm;
return;
}
void push_down(ll p,ll pl,ll pr) {
if(tap[p]!=0) {
ll mid=(pl+pr)/2;
addtag(p1,pl,mid,tap[p]);
addtag(p2,mid+1,pr,tap[p]);
tap[p]=0;
}
if(tap1[p]!=0){
ll mid=(pl+pr)/2;
addtag1(p1,pl,mid,tap1[p]);
addtag1(p2,mid+1,pr,tap1[p]);
tap1[p]=0;
}
}
void update(ll L,ll R,ll p,ll pl,ll pr,ll d) {
push_down(p,pl,pr);
if(pl>=L&&R>=pr) {
addtag(p,pl,pr,d);
return;
}
ll mid=(pl+pr)/2;
if(mid>=L) update(L,R,p1,pl,mid,d);
if(mid<R) update(L,R,p2,mid+1,pr,d);
push_up(p);
return;
}
void update1(ll L,ll R,ll p,ll pl,ll pr,ll d){
if(pl>=L&&R>=pr) {
addtag1(p,pl,pr,d);
return;
}
push_down(p,pl,pr);
ll mid=(pl+pr)/2;
if(mid>=L) update1(L,R,p1,pl,mid,d);
if(mid<R) update1(L,R,p2,mid+1,pr,d);
push_up(p);
}
ll qe(ll L,ll R,ll p,ll pl,ll pr) {
if(pl>=L&&pr<=R) return tree[p];
push_down(p,pl,pr);
ll ret=0;
ll mid=(pl+pr)/2;
if(mid>=L) ret+=qe(L,R,p1,pl,mid);
if(R>mid) ret+=qe(L,R,p2,mid+1,pr);
return ret;
}
int main() {
cin>>n>>m>>mm;
for(int i=1; i<=n; i++) {
cin>>a[i];
}
built(1,1,n);
for(long long i=1; i<=m; i++) {
ll q,le,re,t;
cin>>q>>le>>re;
if(q==3) cout<<qe(le,re,1,1,n)%mm<<endl;
if(q==2) {
cin>>t;
update(le,re,1,1,n,t);
}
if(q==1){
cin>>t;
update1(le,re,1,1,n,t);
}
}
return 0;
}