#include <bits/stdc++.h>
using namespace std;
#define int long long
int f[400010],mul[400010],a[100010],add[400010],n,m,mod;
void up(int root)
{
f[root]=(f[2*root]+f[2*root+1])%mod;
}
void build(int root,int l,int r)
{
mul[root]=1;
add[root]=0;
if(l==r)
{
f[root]=a[l]%mod;
}
else
{
int m=(l+r)/2;
build(root*2,l,m);
build(root*2+1,m+1,r);
up(root);
}
return;
}
void pushdown(int root,int l,int r)
{
int m=(l+r)/2;
f[root*2]=(f[root*2]*mul[root]+add[root]*(m-l+1))%mod;
f[root*2+1]=(f[root*2+1]*mul[root]+add[root]*(r-m))%mod;
mul[root*2]=(mul[root*2]*mul[root])%mod;
mul[root*2+1]=(mul[root*2+1]*mul[root])%mod;
add[root*2]=(add[root*2]*mul[root]+add[root])%mod;
add[root*2+1]=(add[root*2+1]*mul[root]+add[root])%mod;
mul[root]=1;
add[root]=0;
return;
}
int query(int root,int l,int r,int x,int y)
{
if(r<x||l>y) return 0;
if(x<=l&&r<=y) return f[root];
pushdown(root,l,r);
int mid=(l+r)>>1;
int ans=0;
ans+=query(2*root,l,mid,x,y),ans%=mod;
ans+=query(2*root+1,mid+1,r,x,y),ans%=mod;
return ans;
}
void update1(int root,int l,int r,int x,int y,int p)
{
if(r<x||l>y) return;
if(x<=l&&r<=y)
{
add[root]+=p;
add[root]%mod;
f[root]=(f[root]+((r-l+1)*p)%mod)%mod;
return;
}
pushdown(root,l,r);
int mid=(l+r)>>1;
update1(2*root,l,mid,x,y,p);
update1(2*root+1,mid+1,r,x,y,p);
up(root);
return;
}
void update2(int root,int l,int r,int x,int y,int p)
{
if(r<x||l>y) return;
if(x<=l&&r<=y)
{
mul[root]*=p;
mul[root]%=mod;
f[root]=f[root]*((r-l+1)*p%mod)%mod;
add[root]*=p;
add[root]%=mod;
return;
}
pushdown(root,l,r);
int mid=(l+r)>>1;
update2(2*root,l,mid,x,y,p);
update2(2*root+1,mid+1,r,x,y,p);
up(root);
return;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>mod;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
build(1,1,n);
for(int i=1;i<=m;i++)
{
int x,y,op,k;
cin>>op>>x>>y;
if(op==1)
{
cin>>k;
update2(1,1,n,x,y,k);
}
if(op==2)
{
cin>>k;
update1(1,1,n,x,y,k);
}
if(op==3)
{
cout<<query(1,1,n,x,y)<<endl;
}
}
return 0;
}