// //线段树2
#include <bits/stdc++.h>
#define ll long long
#define ls p << 1
#define rs p << 1 | 1
using namespace std;
const int maxn = 100010;
ll a[maxn];
int n, m, q;
struct tree
{
int l, r;
long long val, add, mul;
} t[4 * maxn + 2];
void pushup(int p)
{
t[p].val = (t[ls].val + t[rs].val) % m;
}
void bulid(int p, int l, int r)
{
t[p].l = l;
t[p].r = r;
t[p].mul = 1;
if (l == r)
{
t[p].val = a[l] % m;
return;
}
int mid = l + r >> 1;
bulid(ls, l, mid);
bulid(rs, mid + 1, r);
pushup(p);
}
void pushdown(int p)
{
t[ls].val = (t[ls].val * t[p].mul + t[p].add * (t[ls].r - t[ls].l + 1)) % m;
t[rs].val = (t[rs].val * t[p].mul + t[p].add * (t[rs].r - t[rs].l + 1)) % m;
t[ls].mul = (t[ls].mul * t[p].mul) % m;
t[rs].mul = (t[rs].mul * t[p].mul) % m;
t[ls].add = (t[ls].add * t[p].mul) % m;
t[rs].add = (t[rs].add * t[p].mul) % m;
t[p].add = 0;
t[p].mul = 1;
}
void changeAdd(int p, int L, int R, long long num)
{
if (L <= t[p].l && R >= t[p].r)
{
t[p].val = (t[p].val + num * (t[p].r - t[p].l + 1)) % m;
t[p].add = (num + t[p].add) % m;
return;
}
pushdown(p);
int mid = t[p].l + t[p].r >> 1;
if (L <= mid)
changeAdd(ls, L, R, num);
if (R > mid)
changeAdd(rs, L, R, num);
pushup(p);
}
void changeMul(int p, int L, int R, long long num)
{
if (L <= t[p].l && R >= t[p].r)
{
t[p].add = (t[p].add * num) % m;
t[p].mul = (t[p].mul * num) % m;
t[p].val = (t[p].val * num) % m;
return;
}
pushdown(p);
int mid = t[p].l + t[p].r >> 1;
if (L <= mid)
changeMul(ls, L, R, num);
if (R > mid)
changeMul(rs, L, R, num);
pushup(p);
}
long long query(int p, int L, int R)
{
if (L <= t[p].l && R >= t[p].r)
return t[p].val;
pushdown(p);
int mid = t[p].l + t[p].r >> 1;
long long ans = 0;
if (L <= mid)
{
ans += query(ls, L, R);
ans %= m;
}
if (R > mid)
{
ans += query(rs, L, R);
ans %= m;
}
return ans;
}
int main()
{
scanf("%d%d%d", &n, &q, &m);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
bulid(1, 1, n);
for (int i = 1; i <= q; i++)
{
int opt, x, y;
long long k;
scanf("%d", &opt);
if (opt == 1)
{
scanf("%d%d%lld", &x, &y, &k);
changeMul(1, x, y, k);
}
else if (opt == 2)
{
scanf("%d%d%lld", &x, &y, &k);
changeAdd(1, x, y, k);
}
else
{
scanf("%d%d", &x, &y);
printf("%lld\n", query(1, x, y));
}
}
return 0;
}
照tj打的,样例不过