#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#define cios ios::sync_with_stdio(false),cin.tie(0)
const int maxn = 1000002;
using namespace std;
typedef long long LL;
LL nadd,ql,qr,muitiply;
LL ans,mod;
struct node{
LL w;
LL l , r , f , mu;
} tree[maxn] ;
inline void read(LL &x)
{
int f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while(s<='9'&&s>='0'){x=10*x+s-48;s=getchar();}
x*=f;
}
void build( int k , int l , int r)
{
tree[k].l = l;
tree[k].r = r;
tree[k].mu = 1 ;
tree[k].f = 0 ;
if( l == r )
{
LL temp;
read(temp);
tree[k].w = temp % mod;
return ;
}
LL m = ( tree[k].l + tree[k].r ) >> 1;
build( 2*k , l , m );
build( 2*k+1 , m+1 , r );
tree[k].w = ( tree[2*k].w + tree[2*k+1].w ) % mod;
}
void down(int k)
{
tree[2*k].w = ( ( tree[2*k].w * tree[k].mu ) % mod + ( ( tree[2*k].r - tree[2*k].l + 1 ) * tree[k].f ) % mod) % mod;
tree[2*k+1].w = ( ( tree[2*k+1].w * tree[k].mu ) % mod + ( ( tree[2*k+1].r - tree[2*k+1].l + 1 ) * tree[k].f ) % mod ) % mod;
tree[2*k].mu = ( tree[2*k].mu * tree[k].mu ) % mod ;
tree[2*k+1].mu = ( tree[2*k+1].mu * tree[k].mu ) % mod ;
tree[2*k].f = ( tree[2*k].f + tree[k].f ) % mod;
tree[2*k+1].f = ( tree[2*k+1].f + tree[k].f ) % mod;
tree[k].mu = 1;
tree[k].f = 0;
}
void add_interval(int k)
{
if( ql <= tree[k].l && qr >= tree[k].r )
{
tree[k].w = ( tree[k].w % mod + ( ( tree[k].r - tree[k].l + 1 ) * nadd ) %mod ) % mod ;
tree[k].f = ( tree[k].f + nadd ) % mod ;
return ;
}
down(k);
int m = ( tree[k].l + tree[k].r ) >> 1;
if(ql<=m) add_interval(2*k);
if(qr>m) add_interval(2*k+1);
tree[k].w = ( tree[2*k].w + tree[2*k+1].w ) % mod ;
}
void muitiply_interval(int k)
{
if( ql <= tree[k].l && qr >= tree[k].r )
{
tree[k].w = ( tree[k].w * muitiply ) % mod;
tree[k].mu = ( tree[k].mu * muitiply ) % mod;
tree[k].f = ( tree[k].f * muitiply ) % mod;
return ;
}
down(k);
int m = ( tree[k].l + tree[k].r ) >> 1;
if(ql<=m) muitiply_interval(2 * k);
if(qr>m) muitiply_interval(2 * k + 1);
tree[k].w = ( tree[2 * k].w + tree[2 * k + 1].w ) % mod;
}
void sum(int k)
{
if( ql <= tree[k].l && qr >= tree[k].r )
{
ans = ( ans + tree[k].w ) % mod;
return ;
}
down(k);
LL m = ( tree[k].l + tree[k].r ) >> 1;
if( ql <= m ) sum(2*k);
if( qr > m ) sum(2*k + 1);
}
int main()
{
long long n,q,sb;
read(n);
read(q);
read(mod);
build(1,1,n);
while(q--)
{
muitiply = 1;
nadd = 0;
ql = 1,
qr = 1;
read(sb);
switch(sb)
{
case 1 :
read(ql);
read(qr);
read(muitiply);
muitiply_interval(1);
break;
case 2:
read(ql);
read(qr);
read(nadd);
add_interval(1);
break;
default :
ans = 0;
read(ql);
read(qr);
sum(1);
printf("%lld\n", ans%mod );
break;
}
}
return 0;
}