#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define int long long
typedef long long ll;
const int N=1e5+5,INF=0x3f3f3f3f;
int mod;
using namespace std;
int n,a[N];
struct segtree
{
int l,r,dat,add,mul;
}t[N<<2];
void build(int p,int l,int r)
{
t[p].l=l;t[p].r=r;t[p].mul=1;
if(l==r){t[p].dat=a[l];return;}
int mid=(l+r)/2;
build(p*2,l,mid);build(p*2+1,mid+1,r);
t[p].dat=t[p*2].dat+t[p*2+1].dat;
}
void spread(int p)
{
if(t[p].mul!=1)
{
t[p*2].dat=t[p*2].dat*t[p].mul%mod;
t[p*2+1].dat=t[p*2+1].dat*t[p].mul%mod;
t[p*2].mul=t[p*2].mul*t[p].mul%mod;
t[p*2+1].mul=t[p*2+1].mul*t[p].mul%mod;
t[p].mul=1;
}
if(t[p].add)
{
t[p*2].dat=(t[p*2].dat+(t[p*2].r-t[p*2].l+1)*t[p].add%mod)%mod;
t[p*2+1].dat=(t[p*2+1].dat+(t[p*2+1].r-t[p*2+1].l+1)*t[p].add%mod)%mod;
t[p*2].add=(t[p*2].add*t[p].mul%mod+t[p].add)%mod;t[p*2+1].add=(t[p*2+1].add*t[p].mul+t[p].add);
t[p].add=0;
}
}
void change_mul(int p,int l,int r,int k)
{
if(l<=t[p].l&&t[p].r<=r) {t[p].dat=t[p].dat*k%mod;t[p].mul=t[p].mul*k%mod;t[p].add=t[p].add*k%mod;return ;}
spread(p);
int mid=(t[p].l+t[p].r)/2;
if(l<=mid) change_mul(p*2,l,r,k);
if(r>mid) change_mul(p*2+1,l,r,k);
t[p].dat=(t[p*2].dat+t[p*2+1].dat)%mod;
return ;
}
void change_add(int p,int l,int r,int k)
{
if(t[p].l>=l&&t[p].r<=r){t[p].dat=(t[p].dat+(t[p].r-t[p].l+1)*k)%mod;t[p].add=(t[p].add+k)%mod;return ;}
spread(p);
int mid=(t[p].l+t[p].r)/2;
if(l<=mid) change_add(p*2,l,r,k);
if(r>mid) change_add(p*2+1,l,r,k);
t[p].dat=t[p*2].dat+t[p*2+1].dat;
}
int query(int p,int l,int r)
{
if(t[p].l>=l&&t[p].r<=r) return t[p].dat;
spread(p);
int mid=(t[p].l+t[p].r)/2,sum=0;
if(l<=mid) sum+=query(p*2,l,r);
if(r>mid) sum+=query(p*2+1,l,r);
return sum%mod;
}
signed main()
{
int Q;
scanf("%lld%lld%lld",&n,&Q,&mod);
FOR(i,1,n) scanf("%lld",&a[i]);
build(1,1,n);
while(Q--)
{
int opt,x,y,k;
scanf("%lld%lld%lld",&opt,&x,&y);
if(opt==1) scanf("%lld",&k),change_mul(1,x,y,k);
else if(opt==2) scanf("%lld",&k),change_add(1,x,y,k);
else printf("%lld\n",query(1,x,y));
}
return 0;
}