#include <iostream>
#define N 1010
#define int long long
using namespace std;
struct Node {
int l, r;
int val;
int add = 0;
int mul = 1;
}tr[N*4];
int n, q, m, a[N];
void pushup(int u)
{
tr[u].val = (tr[u << 1].val + tr[u << 1 | 1].val) % m;
}
void pushdown(int u)
{
auto& root = tr[u], & left = tr[u << 1], & right = tr[u << 1 | 1];
if (root.mul != 1)
{
//left.mul *= root.mul % m; left.mul %= m; left.val *= root.mul % m; left.val %= m;
left.mul = (left.mul * root.mul) % m;
left.val = (left.val * root.mul) % m;
//right.mul *= root.mul % m; right.mul %= m; right.val *= root.mul % m; right.val %= m;
right.mul = (right.mul * root.mul) % m;
right.val = (right.val * root.mul) % m;
root.mul = 1;
}
if (root.add) {
//left.add += root.add % m; left.add %= m; left.val += ((left.r - left.l + 1) * root.add) % m; left.val %= m;
left.add = (left.add + root.add) % m;
left.val = (left.val + ((left.r - left.l + 1) * root.add) ) % m;
//right.add += root.add % m; right.add %= m; right.val += ((right.r - right.l + 1) * root.add) % m; right.val %= m;
right.add = (right.add + root.add) % m;
right.val = (right.val + ((right.r - right.l + 1) * root.add) ) % m;
root.add = 0;
}
}
void build(int u, int l, int r)
{
tr[u] = { l, r, 0, 0, 1};
if (l == r) { tr[u].val = a[l] % m; return; }
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void add(int u, int l, int r, int d)
{
if (tr[u].l >= l && tr[u].r <= r) {
//tr[u].add += d % m; tr[u].add %= m;
tr[u].add = ( tr[u].add + d ) % m;
//tr[u].val += (tr[u].r - tr[u].l + 1) * d % m; tr[u].val %= m;
tr[u].val = (tr[u].val + (tr[u].r - tr[u].l + 1) * d) % m;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
pushdown(u);
if (l <= mid) add(u << 1, l, r, d);
if (r > mid) add(u << 1 | 1, l, r, d);
pushup(u);
}
void mul(int u, int l, int r, int d) {
if (tr[u].l >= l && tr[u].r <= r) {
//tr[u].mul *= d % m; tr[u].mul %= m;
tr[u].mul = (tr[u].mul * d) % m;
//tr[u].add *= d % m; tr[u].add %= m;
tr[u].add = (tr[u].add * d) % m;
//tr[u].val *= d % m; tr[u].val %= m;
tr[u].val = (tr[u].val * d) % m;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
pushdown(u);
if (l <= mid) mul(u << 1, l, r, d);
if (r > mid) mul(u << 1 | 1, l, r, d);
pushup(u);
}
int query(int u, int l, int r)
{
if (tr[u].l >= l && tr[u].r <= r) {
return tr[u].val % m;
}
int mid = tr[u].l + tr[u].r >> 1;
int ans = 0;
pushdown(u);
if (l <= mid)
{
ans = (ans + query(u << 1, l, r));
}
if (r > mid)
{
ans = (ans + query(u << 1 | 1, l, r));
}
return ans % m;
}
signed main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> q >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
build(1, 1, n);
while (q--) {
int c, l, r, k;
cin >> c;
if (c == 1) {
cin >> l >> r >> k;
mul(1, l, r, k);
}
else if (c == 2) {
cin >> l >> r >> k;
add(1, l, r, k);
}
else {
cin >> l >> r;
cout << query(1, l, r) << "\n";
}
}
return 0;
}