#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e6 + 10;
int times;
int n,q,mod;
int arr[N],d[N],b1[N],b2[N];
void push(int m,int s,int t,int p)
{
d[p*2]=(d[p*2]*b2[p]%mod+(m-s+1)*b1[p]%mod)%mod;
d[p*2+1]=(d[p*2+1]*b2[p]+(t-m)*b1[p])%mod;
b2[p*2]=(b2[p*2]*b2[p])%mod,b2[p*2+1]=(b2[p*2+1]*b2[p])%mod;
b1[p*2]=(b1[p*2]*b2[p]+b1[p])%mod,b1[p*2+1]=(b1[p*2+1]*b2[p]+b1[p])%mod;
b2[p]=1;
b1[p]=0;
}
void build(int s,int t,int p)
{
if(s==t)
{
d[p]=arr[s];
return;
}
int m = s+((t-s)>>1);
build(s,m,p*2);
build(m+1,t,p*2+1);
d[p]=(d[p*2]+d[p*2+1])%mod;
}
void update_add(int l,int r,int c,int s,int t,int p)
{
if(r<s||l>t)return;
if(s>=l&&t<=r)
{
d[p]=(d[p]+(t-s+1)*c%mod)%mod,b1[p]=(b1[p]+c)%mod;
return;
}
int m = s+((t-s)>>1);
if(b1[p]||b2[p]!=1)push(m,s,t,p);
update_add(l,r,c,s,m,p*2);
update_add(l,r,c,m+1,t,p*2+1);
d[p]=(d[p*2]+d[p*2+1])%mod;
}
void update_mul(int l,int r,int c,int s,int t,int p)
{
if(r<s||l>t)return;
if(s>=l&&r>=t)
{
d[p]=(d[p]*c)%mod;
b2[p]=(b2[p]*c)%mod;
b1[p]=(b1[p]*c)%mod;
return;
}
int m = s+((t-s)>>1);
if(b1[p]||b2[p]!=1)push(m,s,t,p);
update_add(l,r,c,s,m,p*2);
update_add(l,r,c,m+1,t,p*2+1);
d[p]=(d[p*2]+d[p*2+1])%mod;
}
int query(int l,int r,int s,int t,int p)
{
if(r<s||l>t)return 0;
if(s>=l&&t<=r)return d[p]%mod;
int m = s+((t-s)>>1);
if(b1[p]||b2[p]!=1)push(m,s,t,p);
return (query(l,r,s,m,p*2)+query(l,r,m+1,t,p*2+1))%mod;
}
void solve()
{
cin>>n>>q>>mod;
for(int i=1;i<=n;i++)cin>>arr[i];
for(int i=1;i<=N;i++)b2[i]=1;
build(1,n,1);
while(q--)
{
int op;
int x,y,k;
cin>>op;
if(op==1)
{
cin>>x>>y>>k;
update_mul(x,y,k,1,n,1);
}
else if(op==2)
{
cin>>x>>y>>k;
update_add(x,y,k,1,n,1);
}
else
{
cin>>x>>y;
cout<<query(x,y,1,n,1)<<endl;
}
}
}
signed main()
{
std::ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
times=1;
while (times--)
{
solve();
}
return 0;
}