#include"iostream"
using namespace std;
#define ls (i<<1)
#define rs (ls|1)
#define mid ((l+r)>>1)
typedef long long ll;
const ll N=1e6+10;
ll tree[N<<2],mul[N<<2],add[N<<2],p,n,m;
void build(ll i,ll l,ll r)
{
mul[i]=1;
if(l==r) cin>>tree[i];
else
{
build(ls,l,mid),build(rs,mid+1,r);
tree[i]=(tree[ls]+tree[rs])%p;
}
}
void pushdown(ll i,ll l,ll r)
{
if(add[i]==0&&mul[i]==0) return ;
mul[ls]=((mul[ls]%p)*(mul[i]%p))%p;
mul[rs]=((mul[rs]%p)*(mul[i]%p))%p;
add[ls]=((((add[ls]%p)*(mul[i]%p))%p)+(add[i]%p))%p;
add[rs]=((((add[rs]%p)*(mul[i]%p))%p)+(add[i]%p))%p;
tree[ls]=((tree[ls]%p)*(mul[i]%p))%p;
tree[ls]=((tree[ls]%p)+(((add[i]%p)*((mid-l+1)%p))%p))%p;
tree[rs]=((tree[rs]%p)*(mul[i]%p))%p;
tree[rs]=((tree[rs]%p)+(((add[i]%p)*((r-mid)%p))%p))%p;
add[i]=0,mul[i]=1;
}
void Mul(ll i,ll l,ll r,ll L,ll R,ll k)
{
if(r<L||l>R) return;
else if(L<=l&&R>=r)
{
tree[i]=((tree[i]%p)*(k%p))%p;
mul[i]=((mul[i]%p)*(k%p))%p;
add[i]=((add[i]%p)*(k%p))%p;
}
else
{
pushdown(i,l,r);
Mul(ls,l,mid,L,R,k),Mul(rs,mid+1,r,L,R,k);
tree[i]=((tree[ls]%p)+(tree[rs]%p))%p;
}
}
void Add(ll i,ll l,ll r,ll L,ll R,ll k)
{
if(r<L||l>R) return;
else if(L<=l&&R>=r)
{
tree[i]=((tree[i]%p)+(((k%p)*((r-l+1)%p))%p))%p;
add[i]=((add[i]%p)+(k%p))%p;
}
else
{
pushdown(i,l,r);
Add(ls,l,mid,L,R,k),Add(rs,mid+1,r,L,R,k);
tree[i]=((tree[ls]%p)+(tree[rs]%p))%p;
}
}
ll query(ll i,ll l,ll r,ll L,ll R)
{
if(r<L||l>R) return 0;
else if(L<=l&&R>=r) return tree[i];
else
{
pushdown(i,l,r);
return ((query(ls,l,mid,L,R)%p)+(query(rs,mid+1,r,L,R)%p))%p;
}
}
void solve()
{
cin>>n>>m>>p;
build(1,1,n);
for(ll i=1;i<=m;i++)
{
ll op;
cin>>op;
if(op==1)
{
ll l,r,k;
cin>>l>>r>>k;
Mul(1,1,n,l,r,k);
}
else if(op==2)
{
ll l,r,k;
cin>>l>>r>>k;
Add(1,1,n,l,r,k);
}
else
{
ll l,r;
cin>>l>>r;
cout<<query(1,1,n,l,r)<<"\n";
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
solve();
return 0;
}