#include <iostream>
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
ll a[N];
struct node
{
int l, r;
ll sum;
ll add, mul;//懒标记 先乘后加
}tr[4 * N];
ll n, m, p;
void pushup(int u)
{
tr[u].sum = (tr[2 * u].sum + tr[2 * u + 1].sum) % p;
}
void pushdown(int u)
{
node& root = tr[u], & left = tr[2 * u], & right = tr[2 * u + 1];
left.sum = (left.sum * root.mul + (left.r - left.l + 1) * root.add) % p;
right.sum = (right.sum * root.mul + (right.r - right.l + 1) * root.add) % p;
left.add = (left.add * root.mul + root.add) % p; left.mul = (left.mul * root.mul) % p;
right.add = (right.add * root.mul + root.add) % p; right.mul = (right.mul * root.mul) % p;
root.add = 0, root.mul = 1;
}
void build(int u, int l, int r)
{
if (l == r) tr[u] = { l,r,a[l],0,1 };
else
{
tr[u] = { l,r,0,0,1 };
int mid = l + r >> 1;
build(2 * u, l, mid); build(2 * u + 1, mid + 1, r);
pushup(u);
}
}
void modify(int u, int l, int r, int add, int mul)
{
if (l <= tr[u].l && r >= tr[u].r)
{
tr[u].add = (tr[u].add * mul + add )% p;
tr[u].mul = (tr[u].mul * mul )% p;
tr[u].sum = (((tr[u].sum * mul) + (tr[u].r - tr[u].l + 1) *add)) % p;
}
else
{
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid) modify(2 * u, l, r, add, mul);
if (r > mid) modify(2 * u + 1, l, r, add, mul);
pushup(u);
}
}
ll query(int u, int l, int r)
{
if (l <= tr[u].l && r >= tr[u].r) return tr[u].sum;
ll res = 0;
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid) res = query(2 * u, l, r) % p;
if (r > mid) res = res + query(2 * u + 1, l, r) % p;
return res;
}
int main()
{
cin >> n >> m >> p;
for (int i = 1; i <= n; i++) cin >> a[i];
build(1, 1, n);
while (m--)
{
int op, x, y;
cin >> op >> x >> y;
if (op == 3)
{
cout << query(1, x, y) << endl;
}
else if (op == 1)//乘
{
ll k;
cin >> k;
modify(1, x, y, 0, k);
}
else//加
{
ll k;
cin >> k;
modify(1, x, y, 1, k);
}
}
}