#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#define N 100010
using namespace std;
struct node{
int l,r,atag,mtag=1,sum;
}c[N];
int n,m,p,a[N];
inline void read(int &x)
{
char c=0;x=0;
while(!isdigit(c))c=getchar();
while(isdigit(c))x=x*10+c-'0',c=getchar();
}
void update(int x)
{
c[x].sum=(c[x<<1].sum+c[x<<1|1].sum)%p;
}
void pushdown(int x)
{
c[x<<1].sum=(c[x<<1].sum*c[x].mtag+(c[x<<1].r-c[x<<1].l+1)*c[x].atag*c[x].mtag)%p;
c[x<<1|1].sum=(c[x<<1|1].sum*c[x].mtag+(c[x<<1|1].r-c[x<<1|1].l+1)*c[x].atag*c[x].mtag)%p;
c[x<<1].mtag=(c[x].mtag*c[x<<1].mtag)%p;
c[x<<1|1].mtag=(c[x].mtag*c[x<<1|1].mtag)%p;
c[x<<1].atag=(c[x].atag+c[x<<1].atag*c[x].mtag)%p;
c[x<<1|1].atag=(c[x].atag+c[x<<1|1].atag*c[x].mtag)%p;
c[x].atag=0;
c[x].mtag=1;
}
void build(int l,int r,int x)
{
c[x].l=l,c[x].r=r;
if(l==r){
c[x].sum=a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,x<<1);
build(mid+1,r,x<<1|1);
update(x);
}
int query(int l,int r,int x)
{
if(c[x].l>=l&&c[x].r<=r)
return c[x].sum;
pushdown(x);
int mid=(c[x].l+c[x].r)>>1;
int ans=0;
if(l<=mid)ans=(ans+query(l,r,x<<1))%p;
if(r>mid)ans=(ans+query(l,r,x<<1|1))%p;
return ans;
}
void change1(int l,int r,int x,int z)
{
if(c[x].l>=l&&c[x].r<=r){
c[x].sum=(c[x].sum+z*(c[x].r-c[x].l+1))%p;
c[x].atag=(c[x].atag+z)%p;
return;
}
pushdown(x);
int mid=(c[x].l+c[x].r)>>1;
if(l<=mid)change1(l,r,x<<1,z);
if(r>mid)change1(l,r,x<<1|1,z);
update(x);
}
void change2(int l,int r,int x,int z)
{
if(c[x].l>=l&&c[x].r<=r){
c[x].atag=(c[x].atag*z)%p;
c[x].sum=(c[x].sum*z)%p;
c[x].mtag=(c[x].mtag*z)%p;
return;
}
pushdown(x);
int mid=(c[x].l+c[x].r)>>1;
if(l<=mid)change2(l,r,x<<1,z);
if(r>mid)change2(l,r,x<<1|1,z);
update(x);
}
int main()
{
read(n),read(m),read(p);
for(int i=1;i<=n;++i)read(a[i]);
build(1,n,1);
for(int i=1;i<=m;++i){
int a,b,c,d;
read(a);
if(a==1){
read(b),read(c),read(d);
change2(b,c,1,d);
}
if(a==2){
read(b),read(c),read(d);
change1(b,c,1,d);
}
if(a==3){
read(b),read(c);
cout<<query(b,c,1)%p<<endl;
}
}
return 0;
}