//Segment Tree
//By AcerMo
#include
#include
#include
#include
#include
using namespace std;
const int M=500500;
struct Tree
{
long long int son[2],lazy[2];
long long int mks[3],bond[2];
long long int asum;
}tree[M*4];
int num[M];
int n,m,root=0,cnt=1,mod;
void pushup(int cur)
{
int ls=tree[cur].son[0];
int rs=tree[cur].son[1];
tree[cur].bond[0]=tree[ls].bond[0];
tree[cur].bond[1]=tree[rs].bond[1];
tree[cur].asum=tree[ls].asum+tree[rs].asum;
}
void built(int L,int R,int cur)
{
tree[cur].lazy[0]=0;tree[cur].lazy[1]=1;
if (R==L)
{
tree[cur].asum=num[L];
tree[cur].son[0]=tree[cur].son[1]=-1;
tree[cur].bond[0]=tree[cur].bond[1]=L;
return ;
}
tree[cur].son[0]=cnt++;
tree[cur].son[1]=cnt++;
int mid=(L+R)>>1;
built(L,mid,tree[cur].son[0]);
built(mid+1,R,tree[cur].son[1]);
pushup(cur);
}
void pushdown(int cur)
{
int lson=tree[cur].son[0], rson=tree[cur].son[1];
tree[lson].asum=(tree[lson].asum*tree[cur].lazy[1]+tree[cur].lazy[0]*(tree[lson].bond[1]-tree[lson].bond[0]+1))%mod;
tree[rson].asum=(tree[rson].asum*tree[cur].lazy[1]+tree[cur].lazy[0]*(tree[rson].bond[1]-tree[rson].bond[0]+1))%mod;
tree[lson].lazy[1]=(tree[lson].lazy[1]*tree[cur].lazy[1])%mod;
tree[rson].lazy[1]=(tree[rson].lazy[1]*tree[cur].lazy[1])%mod;
tree[lson].lazy[0]=(tree[lson].lazy[0]*tree[cur].lazy[1]+tree[cur].lazy[0])%mod;
tree[rson].lazy[0]=(tree[rson].lazy[0]*tree[cur].lazy[1]+tree[cur].lazy[0])%mod;
tree[cur].lazy[1]=1;tree[cur].lazy[0]=0;
}
void updateadd(int L,int R,int val,int cur)
{
if (L<=tree[cur].bond[0]&&tree[cur].bond[1]<=R)
{
tree[cur].asum+=(val*(tree[cur].bond[1]-tree[cur].bond[0]+1));
tree[cur].asum%=mod;tree[cur].lazy[0]+=val;tree[cur].lazy[0]%=mod;
return ;
}
pushdown(cur);
int mid=(tree[cur].bond[0]+tree[cur].bond[1])>>1;
if (L<=mid) updateadd(L,R,val,tree[cur].son[0]);
if (R>mid) updateadd(L,R,val,tree[cur].son[1]);
pushup(cur);
}
void updatemul(int L,int R,int val,int cur)
{
if (L<=tree[cur].bond[0]&&tree[cur].bond[1]<=R)
{
tree[cur].asum*=val;tree[cur].asum%=mod;
tree[cur].lazy[0]*=val;tree[cur].lazy[0]%=mod;
tree[cur].lazy[1]*=val;tree[cur].lazy[1]%=mod;
return ;
}
pushdown(cur);
int mid=(tree[cur].bond[0]+tree[cur].bond[1])>>1;
if (L<=mid) updatemul(L,R,val,tree[cur].son[0]);
if (R>mid) updatemul(L,R,val,tree[cur].son[1]);
pushup(cur);
}
long long int querysum(int L,int R,int cur)
{
long long int tot=0;
if (L<=tree[cur].bond[0]&&tree[cur].bond[1]<=R) return tree[cur].asum;
pushdown(cur);
int mid=(tree[cur].bond[0]+tree[cur].bond[1])>>1;
if (L<=mid) tot+=querysum(L,R,tree[cur].son[0]);
if (R>mid) tot+=querysum(L,R,tree[cur].son[1]);
return tot%mod;
}
int main()
{
scanf("%d %d %d",&n,&m,&mod);
for (int i=1;i<=n;i++) scanf("%d",&num[i]),num[i]%=mod;
built(1,n,root);
while (m--)
{
int a,b,c,d;
scanf("%d",&d);
if (d==1)
{
scanf("%d %d %d",&a,&b,&c);
updatemul(a,b,c,root);
}
else if (d==2)
{
scanf("%d %d %d",&a,&b,&c);
updateadd(a,b,c,root);
}
else if (d==3)
{
scanf("%d %d",&a,&b);
cout<