#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5;
int a[N+100];
int n,q,mod;
struct node
{
int l,r;
ll add,mu,w;
}t[N*4+100];
void up(int k)
{
t[k].w=(t[k<<1].w+t[k<<1|1].w)%mod;
}
void build(int k,int l,int r)
{
t[k].l=l,t[k].r=r;
if(l==r)
{
t[k].w=a[l]%mod;
t[k].mu=1;
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build((k<<1)+1,mid,r);
up(k);
}
void down(int k)
{
t[k<<1].w=(t[k<<1].w*t[k].mu+(t[k<<1].r-t[k<<1].l+1)*t[k].add)%mod;
t[k<<1|1].w=(t[(k<<1)+1].w*t[k].mu+(t[(k<<1)+1].r-t[(k<<1)+1].l+1)*t[k].add)%mod;
t[k<<1].mu=(t[k].mu*t[k<<1].mu)%mod;
t[(k<<1)+1].mu=(t[k].mu*t[(k<<1)+1].mu)%mod;
t[k<<1].add=(t[k<<1].mu*t[k<<1].add+t[k].add)%mod;
t[k<<1|1].add=(t[k<<1|1].add*t[k].mu+t[k].add)%mod;
t[k].add=0;
t[k].mu=1;
return;
}
void add(int k,int x,int y,int v)
{
if(t[k].r<=y && t[k].l>=x)
{
t[k].add+=v;
t[k].w=(t[k].w+(t[k].r-t[k].l+1)*t[k].add)%mod;
}
down(k);
int mid=(t[k].l+t[k].r)>>1;
if(x<=mid)
add(k<<1,x,y,v);
if(y>mid)
add(k<<1|1,x,y,v);
up(k);
return;
}
void mul(int k,int x,int y,int v)
{
if(t[k].r<=y && t[k].l>=x)
{
t[k].add=(t[k].add*v)%mod;
t[k].mu=(t[k].mu*v)%mod;
t[k].w=(t[k].w*t[k].mu)%mod;
}
down(k);
int mid=(t[k].l+t[k].r)>>1;
if(x<=mid)
add(k<<1,x,y,v);
if(y>mid)
add(k<<1|1,x,y,v);
up(k);
return;
}
ll ask(int k,int x,int y)
{
if(t[k].r<=y && t[k].l>=x)
return t[k].w;
down(k);
ll res=0;
int mid=(t[k].l+t[k].r)>>1;
if(x<=mid)
res=(res+ask(k<<1,x,y))%mod;
if(y>mid)
res=(res+ask(k<<1|1,x,y))%mod;
up(k);
return res;
}
int main()
{
cin>>n>>q>>mod;
for(int i=1;i<=n;i++)
cin>>a[i];
while(q--)
{
int k,x,y,v;
cin>>k>>x>>y;
if(k==1)
{
cin>>v;
mul(1,x,y,v);
}
if(k==2)
{
cin>>v;
add(1,x,y,v);
}
else
cout<<ask(1,x,y)<<"\n";
}
return 0;
}