#include<bits/stdc++.h>
using namespace std;
#define MAX 100100
#define ll long long
struct Node{
ll l,r,s,lazy,lbzy;//lazy为加法tag,lbzy为乘法tag
}f[MAX<<2];
ll n,m,a[MAX<<1],top,p,q[MAX],num;
void create(ll node,ll l,ll r)//建树
{
top=max(top,node);
f[node].l=l;
f[node].r=r;
f[node].lazy=0;f[node].lbzy=1;
if(l==r) f[node].s=a[l]%p;
else
{
create(node<<1,l,(l+r)>>1);
create((node<<1)+1,((l+r)>>1)+1,r);
f[node].s=(f[node<<1].s+f[(node<<1)+1].s)%p;
}
return;
}
void pushdown(ll node)//推lazytag
{
if((node<<1) >top) return;
ll l=f[node].l,r=f[node].r,mid=(l+r)>>1;
f[node<<1].s=((f[node<<1].s*f[node].lbzy)%p+((mid-l+1)*f[node].lazy)%p)%p;
f[(node<<1)+1].s=((f[(node<<1)+1].s*f[node].lbzy)%p+((r-mid)*f[node].lazy)%p)%p;
f[node<<1].lazy+=f[node].lazy;
f[node<<1].lazy%=p;
f[node<<1].lbzy*=f[node].lbzy;
f[node<<1].lbzy%=p;
f[(node<<1)+1].lazy+=f[node].lazy;
f[(node<<1)+1].lazy%=p;
f[(node<<1)+1].lbzy*=f[node].lbzy;
f[(node<<1)+1].lbzy%=p;
f[node].lazy=0;
f[node].lbzy=1;
}
void multi(ll node,ll x,ll y,ll k)//乘法
{
ll l=f[node].l,r=f[node].r,mid=(l+r)>>1;
if(x==l && y==r)
{
f[node].s*=k;
f[node].s%=p;
if(l!=r)
{
f[node].lbzy*=k;
f[node].lazy*=k;
f[node].lbzy%=p;
f[node].lazy%=p;
}
}
else
{
if(f[node].lazy) pushdown(node);
if(x>mid) multi((node<<1)+1,x,y,k);
else
{
if(y<=mid) multi(node<<1,x,y,k);
else
{
multi(node<<1,x,mid,k);
multi((node<<1)+1,mid+1,y,k);
}
}
f[node].s=(f[node<<1].s+f[(node<<1)+1].s)%p;
}
}
void add(ll node,ll x,ll y,ll k)//加法
{
ll l=f[node].l,r=f[node].r,mid=(l+r)>>1;
if(x==l && y==r)
{
f[node].s+=(k*(r-l+1))%p;
f[node].s%=p;
if(l!=r)
{
f[node].lazy+=k;
f[node].lazy%=p;
}
}
else
{
if(f[node].lbzy!=1) pushdown(node);
f[node].s+=(k*(y-x+1))%p;
f[node].s%=p;
if(x>mid) add((node<<1)+1,x,y,k);
else
{
if(y<=mid) add(node<<1,x,y,k);
else
{
add(node<<1,x,mid,k);
add((node<<1)+1,mid+1,y,k);
}
}
}
}
ll query(ll node,ll x,ll y)//查询
{
ll ans=0,l=f[node].l,r=f[node].r,mid=(l+r)>>1;
if(x==l && y==r) ans=f[node].s%p;
else
{
if(f[node].lazy || f[node].lbzy!=1) pushdown(node);
if(x>mid) ans=query((node<<1)+1,x,y)%p;
else
{
if(y<=mid) ans=query(node<<1,x,y)%p;
else ans=(query(node<<1,x,mid)%p+query((node<<1)+1,mid+1,y)%p)%p;
}
}
return ans;
}
void operation1()
{
ll x,y,k;
scanf("%lld %lld %lld",&x,&y,&k);
multi(1,x,y,k%p);
}
void operation2()
{
ll x,y,k;
scanf("%lld %lld %lld",&x,&y,&k);
add(1,x,y,k%p);
}
void operation3()
{
ll x,y,ans=0;
scanf("%lld %lld",&x,&y);
printf("%lld\n",query(1,x,y));
}
int main()
{
scanf("%lld %lld %lld",&n,&m,&p);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
create(1,1,n);
int op;
for(int i=1;i<=m;i++)
{
scanf("%d",&op);
if(op==1) operation1();
if(op==2) operation2();
if(op==3) operation3();
}
for(int i=1;i<=num;i++)
printf("%lld\n",q[i]);
return 0;
}