#include <cstdio>
typedef long long LL;
const int N = 1e5 + 10;
struct SGT
{
LL x, add, mul;
};
int n, m, a[N]; LL p;
SGT tr[N << 2];
inline void build (int rt = 1, int l = 1, int r = n)
{
tr[rt].add = 0, tr[rt].mul = 1;
if (l == r) tr[rt].x = a[l];
else
{
int mid = l + r >> 1;
build (rt << 1, l, mid), build (rt << 1 | 1, mid + 1, r);
tr[rt].x = tr[rt << 1].x + tr[rt << 1 | 1].x;
}
tr[rt].x %= p;
}
inline void push_up (int rt)
{
tr[rt].x = (tr[rt << 1].x + tr[rt << 1 | 1].x) % p;
}
inline void push_down (int rt, int mid, int l, int r)
{
tr[rt << 1].x = (tr[rt << 1].x * tr[rt].mul + tr[rt].add * (mid - l + 1)) % p;
tr[rt << 1 | 1].x = (tr[rt << 1 | 1].x * tr[rt].mul + tr[rt].add * (r - mid)) % p;
tr[rt << 1].mul = tr[rt << 1].mul * tr[rt].mul % p;
tr[rt << 1 | 1].mul = tr[rt << 1 | 1].mul * tr[rt].mul % p;
tr[rt << 1].add = (tr[rt << 1].add * tr[rt].mul + tr[rt].add) % p;
tr[rt << 1 | 1].add = (tr[rt << 1 | 1].add * tr[rt].mul + tr[rt].add) % p;
tr[rt].add = 0, tr[rt].mul = 1;
}
inline void update_add (int l, int r, LL k, int rt = 1, int nl = 1, int nr = n)
{
if (l > nr || r < nl) return ;
if (l <= nl && r >= nr) tr[rt].x = (tr[rt].x + k * (nr - nl + 1)) % p, tr[rt].add = (tr[rt].add + k) % p;
else
{
int mid = nl + nr >> 1;
push_down (rt, mid, nl, nr);
update_add (l, r, k, rt << 1, nl, mid), update_add (l, r, k, rt << 1 | 1, mid + 1, nr);
push_up (rt);
}
}
inline void update_mul (int l, int r, LL k, int rt = 1, int nl = 1, int nr = n)
{
if (l > nr || r < nl) return ;
if (l <= nl && r >= nr) tr[rt].x = tr[rt].x * k % p, tr[rt].add = tr[rt].add * k % p, tr[rt].mul = tr[rt].mul * k % p;
else
{
int mid = nl + nr >> 1;
push_down (rt, mid, nl, nr);
update_add (l, r, k, rt << 1, nl, mid), update_add (l, r, k, rt << 1 | 1, mid + 1, nr);
push_up (rt);
}
}
inline LL query (int l, int r, int rt = 1, int nl = 1, int nr = n)
{
if (l > nr || r < nl) return 0;
if (l <= nl && r >= nr) return tr[rt].x;
else
{
int mid = nl + nr >> 1;
push_down (rt, mid, nl, nr);
return (query (l, r, rt << 1, nl, mid) + query (l, r, rt << 1 | 1, mid + 1, nr)) % p;
}
}
int main ()
{
scanf ("%d %d %lld", &n, &m, &p);
for (int i = 1; i <= n; ++i) scanf ("%d", &a[i]);
build ();
while (m--)
{
int opt, x, y; LL k;
scanf ("%d %d %d", &opt, &x, &y);
if (opt == 1) scanf ("%lld", &k), update_mul (x, y, k);
if (opt == 2) scanf ("%lld", &k), update_add (x, y, k);
if (opt == 3) printf ("%lld\n", query (x, y));
}
return 0;
}