只能过三组数据
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
#include <cstdbool>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <iomanip>
#define inf 0x7fffffff
#define ll long long
#define test freopen("input.txt", "r", stdin);
#define qc \
ios::sync_with_stdio(false); \
cin.tie(nullptr);
#define ll long long
#define int long long
using namespace std;
#define maxn ((int)1e6 + 5)
int a[maxn], tree[maxn << 2], lazyadd[maxn << 2], lazymul[maxn << 2];
int N, mod;
void build(int pos = 1, int s = 1, int t = N)
{
lazymul[pos] = 1;
if (s == t)
tree[pos] = a[s];
else
{
int m = s + (t - s >> 1);
build(pos << 1, s, m);
build(pos << 1 | 1, m + 1, t);
tree[pos] = (tree[pos << 1] + tree[pos << 1 | 1]) % mod;
}
}
void pushlazy(int pos, int s, int t)
{
if (s != t)
{
int m = s + (t - s >> 1);
if (lazymul[pos] != 1)
{
tree[pos << 1] *= lazymul[pos];
tree[pos << 1] %= mod;
tree[pos << 1 | 1] *= lazymul[pos];
tree[pos << 1 | 1] %= mod;
lazyadd[pos << 1] *= lazymul[pos];
lazyadd[pos << 1] %= mod;
lazyadd[pos << 1 | 1] *= lazymul[pos];
lazyadd[pos << 1 | 1] %= mod;
lazymul[pos << 1] *= lazymul[pos];
lazymul[pos << 1] %= mod;
lazymul[pos << 1 | 1] *= lazymul[pos];
lazymul[pos << 1 | 1] %= mod;
lazymul[pos] = 1;
}
if (lazyadd[pos])
{
tree[pos << 1] += (m - s + 1) * lazyadd[pos];
tree[pos << 1] %= mod;
tree[pos << 1 | 1] += (t - m) * lazyadd[pos];
tree[pos << 1 | 1] %= mod;
lazyadd[pos << 1] += lazyadd[pos];
lazyadd[pos << 1] %= mod;
lazyadd[pos << 1 | 1] += lazyadd[pos];
lazyadd[pos << 1 | 1] %= mod;
lazyadd[pos] = 0;
}
}
}
void add(int l, int r, int change, int pos = 1, int s = 1, int t = N)
{
if (l <= s && t <= r)
{
tree[pos] += (t - s + 1) * change;
tree[pos] %= mod;
lazyadd[pos] += change;
lazyadd[pos] %= mod;
return;
}
int m = s + (t - s >> 1);
pushlazy(pos, s, t);
if (l <= m)
add(l, r, change, pos << 1, s, m);
if (r > m)
add(l, r, change, pos << 1 | 1, m + 1, t);
tree[pos] = (tree[pos << 1] + tree[pos << 1 | 1]) % mod;
}
void mul(int l, int r, int change, int pos = 1, int s = 1, int t = N)
{
if (l <= s && t <= r)
{
tree[pos] *= change;
tree[pos] %= mod;
lazymul[pos] *= change;
lazymul[pos] %= mod;
lazyadd[pos] *= lazymul[pos];
lazyadd[pos] %= mod;
return;
}
int m = s + (t - s >> 1);
pushlazy(pos, s, t);
if (l <= m)
mul(l, r, change, pos << 1, s, m);
if (r > m)
mul(l, r, change, pos << 1 | 1, m + 1, t);
tree[pos] = (tree[pos << 1] + tree[pos << 1 | 1]) % mod;
}
int query(int l, int r, int pos = 1, int s = 1, int t = N)
{
if (l <= s && t <= r)
return tree[pos];
int m = s + (t - s >> 1);
pushlazy(pos, s, t);
int sum = 0;
if (l <= m)
sum += query(l, r, pos << 1, s, m);
sum%=mod;
if (r > m)
sum += query(l, r, pos << 1 | 1, m + 1, t);
return sum % mod;
}
signed main()
{
qc;
//test;
int m, p;
cin >> N >> m >> mod;
for (int i = 1; i <= N; i++)
cin >> a[i];
build();
while (m--)
{
int op, x, y;
cin >> op >> x >> y;
if (op == 3)
cout << query(x, y) << '\n';
else if (op == 2)
{
int k;
cin >> k;
add(x, y, k);
}
else if(op==1)
{
int k;
cin >> k;
mul(x, y, k);
}
}
return 0;
}