#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const ll M=998244353;
int n,m,tot,op,i,j;
ll k;
ll num[100005],kk;
struct node
{
int l,r;
ll sum,lazy,lazy2=1;
}kuai[100005];
void build()
{
int u=sqrt(n);
while(tot<u)
{
tot++;
kuai[tot].l=1+u*(tot-1);
kuai[tot].r=u*tot;
for(int a=kuai[tot].l;a<=kuai[tot].r;a++)
kuai[tot].sum+=num[a];
}
if(u*tot<n)
{
tot++;
kuai[tot].l=u*(tot-1)+1;
kuai[tot].r=n;
for(int a=kuai[tot].l;a<=kuai[tot].r;a++)
kuai[tot].sum+=num[a];
}
kuai[++tot].l=n+1;
}
void pushdown(int w)
{
ll b=kuai[w].lazy,c=kuai[w].lazy2;
for(int a=kuai[w].l;a<=kuai[w].r;a++)
num[a]=(num[a]*c+b)%kk;
kuai[w].lazy=0;
kuai[w].lazy2=1;
}
void update(int u,int K,int e)
{
int c=1,pos=u;
while(kuai[c].r<u)
{
c++;
}
do
{
if(pos==kuai[c].l&&kuai[c].r<=K)
{
kuai[c].lazy+=e;
kuai[c].lazy%=kk;
kuai[c].sum+=(kuai[c].r-kuai[c].l+1)*e;
}
else if(kuai[c].r>K)
{
if(kuai[c].lazy2!=1)
pushdown(c);
kuai[c].sum+=(K-max(pos,kuai[c].l)+1)*e;
for(int a=max(kuai[c].l,pos);a<=K;a++)
num[a]+=e;
}
else
{
if(kuai[c].lazy2!=1)
pushdown(c);
kuai[c].sum+=(kuai[c].r-pos+1)*e;
for(int a=pos;a<=kuai[c].r;a++)
num[a]+=e;
}
//
c++;
pos=kuai[c].l;
}while(pos<=K);
}
void update2(int u,int K,ll e)
{
int c=1,pos=u;
while(kuai[c].r<u)
{
c++;
}
do
{
if(pos==kuai[c].l&&kuai[c].r<=K)
{
kuai[c].lazy2*=e;
kuai[c].lazy2%=kk;
kuai[c].lazy*=e;
kuai[c].lazy%=kk;
kuai[c].sum=kuai[c].sum*e%kk;
}
else if(kuai[c].r>K)
{
if(kuai[c].lazy||kuai[c].lazy2!=1)
pushdown(c);
kuai[c].sum+=(K-max(pos,kuai[c].l)+1)*e;
for(int a=max(kuai[c].l,pos);a<=K;a++)
{
kuai[c].sum=(kuai[c].sum+num[a]*(e-1))%kk;
num[a]=num[a]*e%kk;
}
}
else
{
if(kuai[c].lazy||kuai[c].lazy2!=1)
pushdown(c);
for(int a=pos;a<=kuai[c].r;a++)
{
kuai[c].sum=(kuai[c].sum+num[a]*(e-1))%kk;
num[a]=num[a]*e%kk;
}
}
c++;
pos=kuai[c].l;
}while(pos<=K);
}
ll query(int w,int a)
{
ll o=0;
int pos=w,c=1;
while(kuai[c].r<w)
c++;
do
{
if(pos==kuai[c].l&&kuai[c].r<=a)
{
o+=kuai[c].sum;
}
else if(kuai[c].r>a)
{
if(kuai[c].lazy||kuai[c].lazy2!=1)
pushdown(c);
for(int b=max(pos,kuai[c].l);b<=a;b++)
o+=num[b];
}
else
{
if(kuai[c].lazy||kuai[c].lazy2!=1)
pushdown(c);
for(int b=pos;b<=kuai[c].r;b++)
o+=num[b];
}
// printf("(%d,%d,%d)",kuai[c].l,kuai[c].r,o);
c++;
pos=kuai[c].l;
}while(pos<=a);
return o;
}
int main()
{
scanf("%d%d%lld",&n,&m,&kk);
for(int a=1;a<=n;a++)
{
scanf("%lld",&num[a]);
}
build();
for(int a=1;a<=m;a++)
{
scanf("%d",&op);
if(op==1)//区间修改(乘)
{
scanf("%d%d%lld",&i,&j,&k);
update2(i,j,k);
}
else if(op==2)//区间修改(加)
{
scanf("%d%d%lld",&i,&j,&k);
update(i,j,k);
}
else//查询
{
scanf("%d%d",&i,&j);
printf("%lld\n",query(i,j)%kk);
}
}
return 0;
}