#include <bits/stdc++.h>
using namespace std;
namespace IO {
template<typename T>
inline T &read(T &x) {
x = 0;
T f = 1;
int ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (!(ch ^ 45)) f = -1;
for (; isdigit(ch); ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
x *= f;
return x;
}
template<typename Firsize_t, typename ...Args>
inline void read(Firsize_t &firsize_t, Args &...args) {
read(firsize_t);
read(args...);
}
class ReadClass {
public:
ReadClass() = default;
template<typename T>
inline ReadClass &operator()(T &x) {
read(x);
return *this;
}
template<typename ...Args>
inline ReadClass &operator()(Args &...args) {
read(args...);
return *this;
}
template<typename Element>
inline ReadClass &array(Element *p, size_t size_tart, size_t end) {
for (size_t i = size_tart; i < end; ++i) {
read(p[i]);
}
return *this;
}
};
template<typename T>
inline void write(T x) {
if (x < 0) putchar(45), x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 ^ 48);
}
class WriteClass {
public:
WriteClass() = default;
template<typename T>
inline WriteClass &operator()(const T &x, const char c = ' ') {
write(x);
putchar(c);
return *this;
}
inline WriteClass &p(const char c) {
putchar(c);
return *this;
}
inline WriteClass &e() {
putchar(10);
return *this;
}
inline WriteClass &s() {
putchar(32);
return *this;
}
inline WriteClass &t() {
putchar(9);
return *this;
}
};
inline void endl() { putchar(10); }
inline void space() { putchar(32); }
inline void tab() { putchar(9); }
ReadClass Read = ReadClass();
WriteClass Write = WriteClass();
#define endl endl()
#define space space()
#define tab tab()
}
using namespace IO;
const int N = 1e5 + 5;
int n, q, m, oper;
int vs[N];
namespace SegmentTrees {
template<class ValueType>
class SegmentNode {
using vt = ValueType;
public:
size_t l, r;
vt v, a, m;
SegmentNode() : l(0), r(0), v(0), a(0), m(0) {}
inline size_t length() const { return r - l + 1; }
};
template<class ValueType, size_t Size>
class SegmentTree {
using vt = ValueType;
using nt = SegmentNode<vt>;
const static size_t sz = Size;
inline static size_t lc(const size_t & i) { return i << 1; }
inline static size_t rc(const size_t & i) { return i << 1 | 1; }
public:
nt v[sz << 2];
void build(const size_t & i, const size_t & l, const size_t & r, vt *values = nullptr) {
v[i].l = l;
v[i].r = r;
v[i].m = 1;
if (l == r) {
if (values != nullptr) v[i].v = (values[l]) % m;
return;
}
const size_t mid = (l + r) >> 1;
build(lc(i), l, mid, values);
build(rc(i), mid + 1, r, values);
pushup(i);
}
void pushdown(const size_t & i) {
const size_t l = v[i].l, r = v[i].r;
const size_t mid = (l + r) >> 1;
v[lc(i)].v = (v[lc(i)].v * v[i].m + v[i].a * (m - l + 1)) % m;
v[rc(i)].v = (v[rc(i)].v * v[i].m + v[i].a * (r - m)) % m;
v[lc(i)].m = (v[lc(i)].m * v[i].m) % m;
v[rc(i)].m = (v[rc(i)].m * v[i].m) % m;
v[lc(i)].a = (v[lc(i)].a * v[i].m + v[i].a) % m;
v[rc(i)].a = (v[rc(i)].a * v[i].m + v[i].a) % m;
v[i].m = 1;
v[i].a = 0;
}
inline void pushup(const size_t & i) {
v[i].v = (v[lc(i)].v + v[rc(i)].v) % m;
}
vt query(const size_t & i, const size_t & l, const size_t & r) {
if (r < v[i].l || l > v[i].r) return 0;
if (l <= v[i].l && v[i].r <= r) return v[i].v;
pushdown(i);
const size_t mid = (l + r) >> 1;
return ((l <= mid ? query(lc(i), l, r) : 0) + (r > mid ? query(rc(i), l, r) : 0)) % m;
}
void add(const size_t & i, const size_t & l, const size_t & r, vt a) {
if (r < v[i].l || l > v[i].r) return;
if (l <= v[i].l && v[i].r <= r) {
v[i].a = (v[i].a + a) % m;
v[i].v = (v[i].v + v[i].length() * a) % m;
return;
}
pushdown(i);
const size_t mid = (l + r) >> 1;
if (l <= mid) add(lc(i), l, r, a);
if (r > mid) add(rc(i), l, r, a);
pushup(i);
}
void mul(const size_t & i, const size_t & l, const size_t & r, vt a) {
if (r < v[i].l || l > v[i].r) return;
if (l <= v[i].l && v[i].r <= r) {
v[i].v = (v[i].v * a) % m;
v[i].a = (v[i].a * a) % m;
v[i].m = (v[i].m * a) % m;
return;
}
pushdown(i);
const size_t mid = (l + r) >> 1;
if (l <= mid) mul(lc(i), l, r, a);
if (r > mid) mul(rc(i), l, r, a);
pushup(i);
}
};
#undef size_t
}
using namespace SegmentTrees;
SegmentTree<int, N> st;
int x, y, k;
signed main() {
Read(n, q, m);
Read.array(vs, 1, n + 1);
st.build(1, 1, n, vs);
while (q-- > 0) {
read(oper);
if (oper == 1) {
Read(x, y, k);
st.mul(1, x, y, k);
} else if (oper == 2) {
Read(x, y, k);
st.add(1, x, y, k);
} else {
Read(x, y);
Write(st.query(1, x, y)).e();
}
}
return 0;
}