#include<bits/stdc++.h>
#define int long long
using namespace std;
struct edge{
int l,r;
int leftchild_id,rightchild_id;
int sum,add,mul;
};
int n,q,mod;
int a[100005];
vector<edge> vt;
void build_tree(int v)
{
if(vt[v].l==vt[v].r)
{
vt[v].sum=a[vt[v].l]%mod;
return;
}
int mid=(vt[v].l+vt[v].r)>>1;
vt.push_back({vt[v].l,mid,0,0,0,0,1});
vt[v].leftchild_id=vt.size()-1;
vt.push_back({mid+1,vt[v].r,0,0,0,0,1});
vt[v].rightchild_id=vt.size()-1;
build_tree(vt[v].leftchild_id);
build_tree(vt[v].rightchild_id);
vt[v].sum=(vt[vt[v].leftchild_id].sum+vt[vt[v].rightchild_id].sum)%mod;
}
void push_down(int v)
{
vt[v].sum=(vt[v].sum*vt[v].mul)%mod;
vt[v].sum=(vt[v].sum+vt[v].add*(vt[v].r-vt[v].l+1))%mod;
if(vt[v].l<vt[v].r)
{
vt[vt[v].leftchild_id].add=(vt[vt[v].leftchild_id].add*vt[v].mul+vt[v].add)%mod;
vt[vt[v].rightchild_id].add=(vt[vt[v].rightchild_id].add*vt[v].mul+vt[v].add)%mod;
vt[vt[v].leftchild_id].mul=(vt[vt[v].leftchild_id].mul*vt[v].mul)%mod;
vt[vt[v].rightchild_id].mul=(vt[vt[v].rightchild_id].mul*vt[v].mul)%mod;
}
vt[v].add=0;
vt[v].mul=1;
return;
}
void mul_change(int v,int l,int r,int k)
{
push_down(v);
if(r<vt[v].l||l>vt[v].r)
{
return;
}
if(r>=vt[v].r&&l<=vt[v].l)
{
vt[v].mul=(vt[v].mul*k)%mod;
vt[v].add=(vt[v].add*k)%mod;
push_down(v);
return;
}
mul_change(vt[v].leftchild_id,l,r,k);
mul_change(vt[v].rightchild_id,l,r,k);
vt[v].sum=(vt[vt[v].leftchild_id].sum+vt[vt[v].rightchild_id].sum)%mod;
}
void add_change(int v,int l,int r,int k)
{
push_down(v);
if(r<vt[v].l||l>vt[v].r)
{
return;
}
if(r>=vt[v].r&&l<=vt[v].l)
{
vt[v].add=(vt[v].add+k)%mod;
push_down(v);
return;
}
add_change(vt[v].leftchild_id,l,r,k);
add_change(vt[v].rightchild_id,l,r,k);
vt[v].sum=(vt[vt[v].leftchild_id].sum+vt[vt[v].rightchild_id].sum)%mod;
}
int query(int v,int l,int r)
{
push_down(v);
if(r<vt[v].l||l>vt[v].r)
{
return 0;
}
if(r>=vt[v].r&&l<=vt[v].l)
{
return vt[v].sum%mod;
}
return (query(vt[v].leftchild_id,l,r)+query(vt[v].rightchild_id,l,r))%mod;
}
void input()
{
cin>>n>>q>>mod;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
vt.push_back({1,n,0,0,0,0,1});
build_tree(0);
for(int i=1;i<=q;i++)
{
int type;
cin>>type;
if(type==1)
{
int x,y,k;
cin>>x>>y>>k;
mul_change(0,x,y,k);
}
else if(type==2)
{
int x,y,k;
cin>>x>>y>>k;
add_change(0,x,y,k);
}
else
{
int x,y;
cin>>x>>y;
cout<<query(0,x,y)%mod<<endl;
}
}
}
signed main()
{
input();
return 0;
}