void build(int x,int l,int r)
{
int mid=(l+r)>>1; mul[x]=1; sum[x]=0;
if(l==r){ sum[x]=a[l]; return;}
build(x2,l,mid);
build(x2+1,mid+1,r);
sum[x]=sum[x2]+sum[x2+1]; MOD(sum[x]);
}
//错误1: add后面有系数
void pushdown(int x,int l,int r)
{
int mid=(l+r)>>1;
sum[x2]=sum[x2]mul[x]+add[x](mid-l+1); MOD(sum[x2]);
sum[x2+1]=sum[x2+1]mul[x]+add[x](r-mid); MOD(sum[x2+1]);
add[x2]=add[x2]mul[x]+add[x]; MOD(add[x2]);
add[x2+1]=add[x2+1]mul[x]+add[x]; MOD(add[x2+1]);
mul[x2]=mul[x]; MOD(mul[x2]);
mul[x2+1]=mul[x]; MOD(mul[x2+1]);
add[x]=0; mul[x]=1;
}
void ADD(int x,int l,int r,int L,int R,int val)
{
int mid=(l+r)>>1;
if(L<=l&&R>=r){ sum[x]+=val(r-l+1); add[x]+=val; //错误:r-l+1
MOD(sum[x]); MOD(add[x]);
return;}
if(add[x]||mul[x]!=1) pushdown(x,l,r);
if(L<=mid) ADD(x2,l,mid,L,R,val);
if(R>mid) ADD(x2+1,mid+1,r,L,R,val);
sum[x]=sum[x2]+sum[x*2+1]; MOD(sum[x]);
}
void MUL(int x,int l,int r,int L,int R,int val)
{
int mid=(l+r)>>1;
if(L<=l&&R>=r){ sum[x]=val; add[x]=val; mul[x]=val;
MOD(sum[x]); MOD(add[x]); MOD(mul[x]);
return;}
if(add[x]||mul[x]!=1) pushdown(x,l,r);
if(L<=mid) MUL(x2,l,mid,L,R,val);
if(R>mid) MUL(x2+1,mid+1,r,L,R,val);
sum[x]=sum[x2]+sum[x*2+1]; MOD(sum[x]);
}
int query(int x,int l,int r,int L,int R)
{
int ans=0;
int mid=(l+r)>>1;
if(L<=l&&R>=r){ return sum[x];}
if(add[x]||mul[x]!=1) pushdown(x,l,r);
if(L<=mid) ans+=query(x2,l,mid,L,R); MOD(ans);
if(R>mid) ans+=query(x2+1,mid+1,r,L,R);MOD(ans);
return ans;
}
signed main()
{
// freopen("data.in","r",stdin);
// freopen("test.out","w",stdout);
n=read();m=read();mod=read();
for(rint i=1;i<=n;i++) a[i]=read(),MOD(a[i]);
build(1,1,n);
while(m--)
{
int opt=read(),x=read(),y=read();
if(opt1){ int k=read(); MUL(1,1,n,x,y,k); }
if(opt2){ int k=read(); ADD(1,1,n,x,y,k); }
if(opt==3){ printf("%lld\n",query(1,1,n,x,y)); }
}
return 0;
}