#include<iostream>
#include<queue>
#define N 100005
using namespace std;
int n,m,mod;
int a[N];
int tree[4*N];
struct fh
{
int f,s;
};
queue<fh>lazy[4*N];
void btree(int l,int r,int x)
{
if(l==r)
{
tree[x]=a[l];
return;
}
int m=(l+r)>>1;
btree(l,m,x*2);
btree(m+1,r,x*2+1);
tree[x]=tree[x*2]+tree[x*2+1];
}
int gtree(int l,int r,int s,int t,int x)
{
if(l<=s && t<=r)
return tree[x];
int m=(s+t)>>1,sum=0;
while(!lazy[x].empty() && s!=t)
{
if(lazy[x].front().f==1)
tree[x*2]*=lazy[x].front().s,
tree[x*2+1]*=lazy[x].front().s,
lazy[x*2].push({1,lazy[x].front().s}),
lazy[x*2+1].push({1,lazy[x].front().s});
if(lazy[x].front().f==2)
tree[x*2]+=lazy[x].front().s,
tree[x*2+1]+=lazy[x].front().s,
lazy[x*2].push({2,lazy[x].front().s}),
lazy[x*2+1].push({2,lazy[x].front().s});
lazy[x].pop();
}
if(l<=m)
sum+=gtree(l,r,s,m,x*2);
if(r>m)
sum+=gtree(l,r,m+1,t,x*2+1);
return sum;
}
void uctree(int l,int r,int s,int t,int c,int x)
{
if(l<=s && t<=r)
{
tree[x]*=c*(t-s+1);
lazy[x].push({1,c});
return;
}
int m=(s+t)>>1;
while(!lazy[x].empty() && s!=t)
{
if(lazy[x].front().f==1)
tree[x*2]*=lazy[x].front().s,
tree[x*2+1]*=lazy[x].front().s,
lazy[x*2].push({1,lazy[x].front().s}),
lazy[x*2+1].push({1,lazy[x].front().s});
if(lazy[x].front().f==2)
tree[x*2]+=lazy[x].front().s,
tree[x*2+1]+=lazy[x].front().s,
lazy[x*2].push({2,lazy[x].front().s}),
lazy[x*2+1].push({2,lazy[x].front().s});
lazy[x].pop();
}
if(l<=m)
uctree(l,r,s,m,c,x*2);
if(r>m)
uctree(l,r,m+1,t,c,x*2+1);
tree[x]=tree[x*2]+tree[x*2+1];
}
void ujtree(int l,int r,int s,int t,int c,int x)
{
if(l<=s && t<=r)
{
tree[x]+=c*(t-s+1);
lazy[x].push({2,c});
return;
}
int m=(s+t)>>1;
while(!lazy[x].empty() && s!=t)
{
if(lazy[x].front().f==1)
tree[x*2]*=lazy[x].front().s,
tree[x*2+1]*=lazy[x].front().s,
lazy[x*2].push({1,lazy[x].front().s}),
lazy[x*2+1].push({1,lazy[x].front().s});
if(lazy[x].front().f==2)
tree[x*2]+=lazy[x].front().s,
tree[x*2+1]+=lazy[x].front().s,
lazy[x*2].push({2,lazy[x].front().s}),
lazy[x*2+1].push({2,lazy[x].front().s});
lazy[x].pop();
}
if(l<=m)
uctree(l,r,s,m,c,x*2);
if(r>m)
uctree(l,r,m+1,t,c,x*2+1);
tree[x]=tree[x*2]+tree[x*2+1];
}
int main()
{
cin>>n>>m>>mod;
for(int i=1;i<=n;i++)
cin>>a[i];
btree(1,n,1);
while(m--)
{
int o,x,y,k;
cin>>o>>x>>y;
if(o==1)
{
cin>>k;
uctree(x,y,1,n,k,1);
}
else if(o==2)
{
cin>>k;
ujtree(x,y,1,n,k,1);
}
else
cout<<gtree(x,y,1,n,1)%mod<<"\n";
}
return 0;
}