#include
#define lson l,m,rt << 1
#define rson m+1,r,rt << 1|1
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int mod = 1000;
ll sum[maxn << 2];
ll add[maxn << 2];
ll mul[maxn << 2];
struct Node {
ll l,r;
ll mid() {
return (l + r) >> 1;
}
} tree[maxn << 2];
void PushUp(ll rt) {
sum[rt] = (sum[rt << 1] + sum[rt << 1|1]) % mod;
}
void PushDown(ll rt,ll len) {
sum[rt << 1]=(sum[rt << 1]*mul[rt]+add[rt]*(len - len/2)) % mod;
sum[rt << 1|1]=(sum[rt << 1|1]*mul[rt]+add[rt]*(len/2)) % mod;
mul[rt << 1]=(mul[rt << 1]*mul[rt]) % mod;
mul[rt << 1|1]=(mul[rt << 1|1]*mul[rt]) % mod;
add[rt << 1]=(add[rt << 1]*mul[rt]+add[rt]) % mod;
add[rt << 1|1]=(add[rt << 1|1]*mul[rt]+add[rt]) % mod;
mul[rt] = 1;
add[rt] = 0;
}
void BuildTree(ll l,ll r,ll rt) {
tree[rt].l = l;
tree[rt].r = r;
if(l == r) {
cin >> sum[rt];
sum[rt] %= mod;
return ;
}
ll m = tree[rt].mid();
BuildTree(lson);
BuildTree(rson);
PushUp(rt);
}
void Updata_add(ll c,ll l,ll r,ll rt) {
if(tree[rt].l ==l && tree[rt].r == r) {
add[rt] = (add[rt] + c) % mod;
sum[rt] = (sum[rt] + (ll) c * (r - l + 1)) % mod;
return ;
}
PushDown(rt,tree[rt].r - tree[rt].l + 1);
ll m = tree[rt].mid();
if(r <= m)
Updata_add(c,l,r,rt << 1);
else if(l > m)
Updata_add(c,l,r,rt << 1|1);
else {
Updata_add(c,lson);
Updata_add(c,rson);
}
PushUp(rt);
}
void Updata_mul(ll c,ll l,ll r,ll rt) {
if(tree[rt].l == l && tree[rt].r == r) {
sum[rt] = (sum[rt]*c) % mod;
mul[rt] = (mul[rt]*c) % mod;
add[rt] = (add[rt]*c) % mod;
return ;
}
PushDown(rt,tree[rt].r - tree[rt].l + 1);
ll m = tree[rt].mid();
if(r <= m)
Updata_mul(c,l,r,rt << 1);
else if(l > m)
Updata_mul(c,l,r,rt << 1|1);
else {
Updata_mul(c,lson);
Updata_mul(c,rson);
}
PushUp(rt);
}
ll Query(ll l,ll r,ll rt) {
if(tree[rt].l == l && tree[rt].r == r) {
return sum[rt];
}
ll m = tree[rt].mid();
ll res = 0;
PushDown(rt,tree[rt].r - tree[rt].l + 1);
if(r <= m)
res = (res + Query(l,r,rt << 1))% mod;
else if(l > m)
res = (res + Query(l,r,rt << 1|1))% mod;
else
res = (res + Query(lson) + Query(rson)) % mod;
return res;
}
int main() {
ll n,m,T;
while(cin >> n >> m >> mod) {
memset(sum,0,sizeof(sum));
memset(add,0,sizeof(add));
for(ll i = 0; i <= n*4; i++)
mul[i] = 1;
BuildTree(1,n,1);
while(m--) {
ll op,x,y,k;
cin >> op;
if(op == 1) {
cin >> x >> y >> k;
Updata_mul(k,x,y,1);
} else if(op == 2) {
cin >> x >> y >> k;
Updata_add(k,x,y,1);
} else {
cin >> x >> y;
printf("%lld\n",Query(x,y,1));
}
}
}
return 0;
}