#include using namespace std; const int N = 1000010; int n, m, p; // 线段树模板 #define LL long long #define ls u << 1 #define rs u << 1 | 1 #define mid ((l + r) >> 1) struct Node { int l, r; int mu, add; LL sum; } tr[N << 2]; void pushup(int u) { tr[u].sum = (tr[ls].sum + tr[rs].sum) % p; } void build(int u, int l, int r) { tr[u].l = l, tr[u].r = r, tr[u].mu = 1; if (l == r) { cin >> tr[u].sum; return; } build(ls, l, mid), build(rs, mid + 1, r); pushup(u); } void pushdown(int u) { if (tr[u].add == 0 && tr[u].mu == 1) return; // 默认懒标记 int &mu = tr[u].mu, &add = tr[u].add; // 此时的add懒标记,已经处理过了 tr[ls].sum = ((LL)mu * tr[ls].sum % p + (LL)(tr[ls].r - tr[ls].l + 1) * add % p) % p; tr[rs].sum = ((LL)mu * tr[rs].sum % p + (LL)(tr[rs].r - tr[rs].l + 1) * add % p) % p; tr[ls].mu = (LL)tr[ls].mu * mu % p; tr[rs].mu = (LL)tr[rs].mu * mu % p; tr[ls].add = ((LL)tr[ls].add * mu % p + add) % p; tr[rs].add = ((LL)tr[rs].add * mu % p + add) % p; mu = 1, add = 0; // 清空懒标记 } void add(int u, int L, int R, int v) { int l = tr[u].l, r = tr[u].r; if (l >= L && r <= R) { tr[u].add = ((LL)tr[u].add + v) % p; tr[u].sum = ((LL)tr[u].sum + v * ((LL)tr[u].r - tr[u].l + 1) % p) % p; return; } if (l > R || r < L) return; pushdown(u); add(ls, L, R, v), add(rs, L, R, v); pushup(u); } void mu(int u, int L, int R, int v) { int l = tr[u].l, r = tr[u].r; if (l >= L && r <= R) { tr[u].add = (LL)tr[u].add * v % p; // 比较重要的一步,add要在这里乘上v,因为后面可能要加其他的数而那些数其实是不用乘k的 tr[u].mu = (LL)tr[u].mu * v % p; tr[u].sum = (LL)tr[u].sum * v % p; return; } if (l > R || r < L) return; pushdown(u); mu(ls, L, R, v), mu(rs, L, R, v); pushup(u); } LL query(int u, int L, int R) { int l = tr[u].l, r = tr[u].r; if (l >= L && r <= R) return tr[u].sum; if (l > R || r < L) return 0; pushdown(u); return (query(ls, L, R) + query(rs, L, R)) % p; } signed main() { // 文件输入输出 #ifndef ONLINE_JUDGE freopen("P3373.in", "r", stdin); #endif // 加快读入 ios::sync_with_stdio(false), cin.tie(0); cin >> n >> m >> p; build(1, 1, n); while (m--) { int op, l, r; cin >> op >> l >> r; if (op == 1) { int k; cin >> k; mu(1, l, r, k); } else if (op == 2) { int k; cin >> k; add(1, l, r, k); } else printf("%lld\n", query(1, l, r)); } return 0; }