#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
using namespace std;
typedef long long int LL;
const int N=1e5+50;
LL n,m,p;
struct date
{
LL sum;
LL l,r,add,mul;
}tree[4*N];
LL arr[N];
void pushup(LL u)
{
tree[u].sum=(tree[u<<1].sum+tree[u<<1|1].sum)%p;
}
void change(LL u,LL Add,LL Mul)
{
tree[u].sum=(tree[u].sum*Mul%p+((tree[u].r-tree[u].l+1)*Add)%p)%p;
tree[u].mul=tree[u].mul*Mul%p;
tree[u].add=(tree[u].add*Mul%p+Add)%p;
}
void pushdown(LL u)
{
if(tree[u].add!=0||tree[u].mul!=1)
{
change(u<<1,tree[u].add,tree[u].mul);
change(u<<1|1,tree[u].add,tree[u].mul);
tree[u].add=0;
tree[u].mul=1;
}
}
void build(LL x,LL l,LL r)
{
tree[x].l=l;
tree[x].r=r;
tree[x].add=0;
tree[x].mul=1;
if(l==r)
{
tree[x].sum=arr[l];
return;
}
LL mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
}
void modify(LL x,LL l,LL r,LL Add,LL Mul)
{
if(tree[x].l>=l&&tree[x].r<=r)
{
change(x,Add,Mul);
return;
}
LL mid=tree[x].l+tree[x].r>>1;
pushdown(x);
if(mid>=l) modify(x<<1,l,r,Add,Mul);
if(r>mid) modify(x<<1|1,l,r,Add,Mul);
pushup(x);
}
LL query(LL u,LL l,LL r)
{
if(tree[u].l>=l&&tree[u].r<=r)
return tree[u].sum;
LL mid=tree[u].l+tree[u].r>>1;
LL res=0;
pushdown(u);
if(mid>=l) res=(res+query(u<<1,l,r))%p;
if(r>mid) res=(res+query(u<<1|1,l,r))%p;
return res;
}
int main()
{
LL i,j;
cin>>n>>m>>p;
for(i=1;i<=n;i++)
{
cin>>arr[i];
}
build(1,1,n);
for(i=1;i<=m;i++)
{
LL w;
cin>>w;
if(w==1)
{
LL w1,w2,w3;
cin>>w1>>w2>>w3;
modify(1,w1,w2,0,w3);
}
else if(w==2)
{
LL w1,w2,w3;
cin>>w1>>w2>>w3;
modify(1,w1,w2,w3,1);
}
else if(w==3)
{
LL w1,w2;
cin>>w1>>w2;
LL t=query(1,w1,w2);
cout<<t<<'\n';
}
}
return 0;
}