#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll n, m, mod, oper, x, y, k;
class segtree
{
public:
#define nd node[now]
#define ndl node[now << 1]
#define ndr node[now<<1|1]
struct segnode
{
ll l, r, val, tag, tag2;
void update(ll x)
{
val += (r - l + 1) * x, tag += x;
val %= mod, tag %= mod;
}
void update2(ll x)
{
val *= x, tag *= x, tag2 *= x;
val %= mod, tag %= mod, tag2 %= mod;
}
};
vector <segnode> node;
ll n;
void pushup(ll now)
{
nd.val = ndl.val + ndr.val;
nd.val %= mod;
}
void pushdown(ll now)
{
if (nd.tag2 > 1)
{
ndl.update2(nd.tag2);
ndr.update2(nd.tag2);
nd.tag2 = 1;
}
if (nd.tag)
{
ndl.update(nd.tag);
ndr.update(nd.tag);
nd.tag = 0;
}
}
void maketree(ll s, ll t, ll now = 1)
{
nd = {s, t, 0, 0, 1};
if (s == t)
{
cin >> nd.val;
return;
}
maketree(s, (s + t) >> 1, now << 1);
maketree(((s + t) >> 1) + 1, t, (now << 1) + 1);
pushup(now);
}
void update(ll s, ll t, ll x, ll now = 1)
{
if (s <= nd.l && t >= nd.r)
{
nd.update(x);
return;
}
pushdown(now);
if (s < ndr.l) update(s, t, x, now << 1);
if (t > ndl.r) update(s, t, x, (now << 1) + 1);
pushup(now);
}
void update2(ll s, ll t, ll x, ll now = 1)
{
if (s <= nd.l && t >= nd.r)
{
nd.update2(x);
return;
}
pushdown(now);
if (s < ndr.l) update2(s, t, x, now << 1);
if (t > ndl.r) update2(s, t, x, (now << 1) + 1);
pushup(now);
}
ll query(ll s, ll t, ll now = 1)
{
if (s <= nd.l && t >= nd.r) return nd.val;
pushdown(now);
ll ret = 0;
if (s < ndr.l) ret += query(s, t, now << 1), ret %= mod;
if (t > ndl.r) ret += query(s, t, (now << 1) + 1), ret %= mod;
return ret;
}
segtree(ll nn)
{
n = nn;
node.resize((n << 2) | 3);
maketree(1, n);
}
};
int main()
{
cin >> n >> m >> mod;
segtree a(n);
while (m--)
{
cin >> oper >> x >> y;
if (oper == 1) cin >> k, a.update2(x, y, k);
else if (oper == 2) cin >> k, a.update(x, y, k);
else cout << a.query(x, y) << endl;
}
}
评测158110837