#include <bits/stdc++.h>
using namespace std;
int n, q, m;
const int MAXN = 1e5 + 10;
int a[MAXN];
int tree[4 * MAXN];
int lazy_add[4 * MAXN], lazy_mul[4 * MAXN];
int ls(int a)
{
return 2 * a;
}
int rs(int a)
{
return 2 * a + 1;
}
void push_up(int p)
{
tree[p] = (tree[ls(p)] + tree[rs(p)]) % m;
}
void build (int p, int l, int r)
{
lazy_mul[p] = 1;
if (l == r)
{
tree[p] = a[l] % m;
return;
}
int mid = (l + r) / 2;
build(ls(p), l, mid);
build(rs(p), mid + 1, r);
push_up(p);
}
void push_down(int p, int l, int r)
{
int mid = (l + r) / 2;
tree[ls(p)] = tree[ls(p)] * lazy_mul[p] + lazy_add[p] * (mid - l + 1);
tree[ls(p)] %= m;
tree[rs(p)] = tree[rs(p)] * lazy_mul[p] + lazy_add[p] * (r - mid);
tree[rs(p)] %= m;
lazy_mul[ls(p)] *= lazy_mul[p];
lazy_mul[rs(p)] *= lazy_mul[p];
lazy_mul[rs(p)] %= m;
lazy_mul[ls(p)] %= m;
lazy_add[ls(p)] = (lazy_add[ls(p)] * lazy_mul[p] + lazy_add[p]) % m;
lazy_add[rs(p)] = (lazy_add[rs(p)] * lazy_mul[p] + lazy_add[p]) % m;
lazy_mul[p] = 1;
lazy_add[p] = 0;
/*
lazy_add[ls(p)] *= lazy_mul[p];
lazy_add[ls(p)] += lazy_add[p];
lazy_add[rs(p)] *= lazy_mul[p];
lazy_add[rs(p)] += lazy_add[p];
tree[p] *= lazy_mul[p];
tree[p] += lazy_add[p] * (r - l + 1);
*/
}
void update_mul(int p, int l, int r, int nl, int nr, int k)
{
if (l >= nl && r <= nr)
{
lazy_add[p] *= k;
lazy_add[p] %= m;
lazy_mul[p] *= k;
lazy_mul[p] %= m;
tree[p] *= k;
tree[p] %= m;
return;
}
push_down(p, l, r);
int mid = (l + r) / 2;
if (nl <= mid)
{
update_mul(ls(p), l, mid, nl, nr, k);
}
if (nr >= mid + 1)
{
update_mul(rs(p), mid + 1, r, nl, nr, k);
}
push_up(p);
}
void update_add(int p, int l, int r, int nl, int nr, int k)
{
if (l >= nl && r <= nr)
{
lazy_add[p] += k;
lazy_add[p] %= m;
tree[p] += k * (r - l + 1) % m;
tree[p] %= m;
return;
}
push_down(p, l, r);
int mid = (l + r) / 2;
if (nl <= mid)
{
update_add(ls(p), l, mid, nl, nr, k);
}
if (nr >= mid + 1)
{
update_add(rs(p), mid + 1, r, nl, nr, k);
}
push_up(p);
}
int query(int p, int l, int r, int nl, int nr)
{
if (l >= nl && r <= nr)
{
return tree[p] % m;
}
int res = 0;
push_down(p, l, r);
int mid = (l + r) / 2;
if (nl <= mid)
{
res += query(ls(p), l, mid, nl, nr) % m;
}
if (nr >= mid + 1)
{
res += query(rs(p), mid + 1, r, nl, nr) % m;
}
return res % m;
}
int main()
{
cin >> n >> q >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
build(1, 1, n);
while (q--)
{
int mod;
cin >> mod;
int x, y, k;
if (mod == 1)
{
cin >> x >> y >> k;
update_mul(1, 1, n, x, y, k);
}
else if (mod == 2)
{
cin >> x >> y >> k;
update_add(1, 1, n, x, y, k);
}
else if (mod == 3)
{
cin >> x >> y;
cout << query(1, 1, n, x, y) << endl;
}
}
return 0;
}