#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q,m,t,x,y,k;
template<typename T>
struct sequence{
private:
mt19937 random;
struct node{
T v,sum,tag1,tag2;int s,p;node*l,*r;
void update(){
sum=v,s=1;
if(l)sum=(sum+l->sum)%m,s+=l->s;
if(r)sum=(sum+r->sum)%m,s+=r->s;
}void push(){
if(l)l->v=(l->v*tag1+tag2)%m,l->tag1=(l->tag1*tag1)%m,l->tag2=(l->tag2*tag1+tag2)%m,l->sum=(l->sum*tag1+l->s*tag2)%m;
if(r)r->v=(r->v*tag1+tag2)%m,r->tag1=(r->tag1*tag1)%m,r->tag2=(r->tag2*tag1+tag2)%m,r->sum=(r->sum*tag1+r->s*tag2)%m;
tag1=1,tag2=0,update();
}
}*root;
node*newnode(T v){
node*p=new node;p->v=v,p->sum=v,
p->tag1=1,p->tag2=0,p->p=random(),
p->s=1,p->l=p->r=0;return p;
}void split(node*p,int k,node*&l,node*&r){
if(!p)return void(l=r=0);
p->push();int s=p->l?p->l->s:0;
if(s+1<=k)split(p->r,k-s-1,p->r,r),l=p;
else split(p->l,k,l,p->l),r=p;
p->update();
}node*merge(node*l,node*r){
if(!l||!r)return l?l:r;
l->push(),r->push();
if(l->p>r->p)return l->r=merge(l->r,r),l->update(),l;
return r->l=merge(l,r->l),r->update(),r;
}
public:
sequence():root(0),random(time(0)){}
void insert(int k,T v){
node*x,*y;split(root,k,x,y),
root=merge(merge(x,newnode(v)),y);
}void mul(int l,int r,T v){
node*x,*y,*z;split(root,r,y,z),
split(y,l-1,x,y),y->tag1=(y->tag1*v)%m,y->v=(y->v*v)%m;
root=merge(merge(x,y),z);
}void add(int l,int r,T v){
node*x,*y,*z;split(root,r,y,z),
split(y,l-1,x,y),y->tag2=(y->tag2+v)%m,y->v=(y->v+v)%m;
root=merge(merge(x,y),z);
}T prod(int l,int r){
node*x,*y,*z;split(root,r,y,z),
split(y,l-1,x,y);T res=y?y->sum:0;
root=merge(merge(x,y),z);return res;
}
};sequence<int>a;
signed main(){
cin>>n>>q>>m;
for(int i=1;i<=n;i++)cin>>t,a.insert(i,t);
while(q--){
cin>>t>>x>>y;
if(t==1)cin>>k,a.mul(x,y,k);
else if(t==2)cin>>k,a.add(x,y,k);
else cout<<a.prod(x,y)<<'\n';
}
}