#include<bits/stdc++.h>
using namespace std;
#define ls (p<<1)
#define rs (p<<1|1)
#define inf 100005
#define int long long
int n,m,mod,a[inf];
int nl,nr,k;
struct node
{
int val;
int mul,add;//乘,加
}tree[inf<<2];
void build(int p,int l,int r)
{
tree[p].mul=1;
tree[p].add=0;
if(l==r){tree[p].val=a[l]%p;return;}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
tree[p].val=(tree[ls].val+tree[rs].val)%mod;
}
void push_down(int p,int l,int r)
{
int mid=(l+r)>>1;
tree[ls].val=(tree[ls].val*tree[ls].mul+tree[p].add*(mid-l+1))%mod;
tree[rs].val=(tree[rs].val*tree[rs].mul+tree[p].add*(r-mid))%mod;
tree[ls].mul=(tree[ls].mul*tree[p].mul)%mod;
tree[rs].mul=(tree[rs].mul*tree[p].mul)%mod;
tree[ls].add=(tree[ls].add*tree[p].mul+tree[p].add)%mod;
tree[rs].add=(tree[rs].add*tree[p].mul+tree[p].add)%mod;
tree[p].mul=1;
tree[p].add=0;
}
void change1(int p,int l,int r)
{
if(nr<l || r<nl)return;
if(nl<=l && r<=nr)
{
tree[p].val=(tree[p].val*k)%mod;
tree[p].mul=(tree[p].mul*k)%mod;
tree[p].add=(tree[p].add*k)%mod;
return;
}
push_down(p,l,r);
int mid=(l+r)>>1;
change1(ls,l,mid);
change1(rs,mid+1,r);
tree[p].val=(tree[ls].val+tree[rs].val)%mod;
}
void change2(int p,int l,int r)
{
if(nr<l || r<nl)return;
if(nl<=l && r<=nr)
{
tree[ls].add=(tree[p].add+k)%mod;
tree[rs].val=(tree[p].val+k)%mod;
return;
}
push_down(p,l,r);
int mid=(l+r)>>1;
change2(ls,l,mid);
change2(rs,mid+1,r);
tree[p].val=(tree[ls].val+tree[rs].val)%mod;
}
int ans(int p,int l,int r)
{
if(nr<l || r<nl)return 0;
if(nl<=l && r<=nr)return tree[p].val;
push_down(p,l,r);
int mid=(l+r)>>1;
return (ans(ls,l,mid)+ans(rs,mid+1,r))%mod;
}
signed main()
{
scanf("%lld %lld %lld",&n,&m,&mod);
for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
build(1,1,n);
for(int i=1;i<=m;++i)
{
int rqyy;
scanf("%lld %lld %lld",&rqyy,&nl,&nr);
if(rqyy==1)
{
scanf("%lld",&k);
change1(1,1,n);
}
if(rqyy==2)
{
scanf("%lld",&k);
change2(1,1,n);
}
if(rqyy==3)
printf("%lld\n",ans(1,1,n));
}
return 0;
}