#include <iostream>
//#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <vector>
#define ll long long
using namespace std;
ll a[100005];
ll tree[400005];
ll lazy_tag[400005] = {0}, mark_m[400005] = {0};
ll n, q, m;
void read(ll &x)
{
ll res = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9')
{
res = res * 10 + c - '0';
c = getchar();
}
x = res;
}
void buid(ll l, ll r, ll p)
{
if(l == r)
{
tree[p] = a[l]; return;
}else
{
ll mid = (l + r) / 2;
buid(l, mid, p << 1);
buid(mid + 1, r, p << 1 | 1);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
}
}
void push_down1(ll p, ll len)
{
lazy_tag[p << 1] += lazy_tag[p];
lazy_tag[p << 1 | 1] += lazy_tag[p];
tree[p << 1] += lazy_tag[p] * (len - len / 2);
tree[p << 1 | 1] += lazy_tag[p] * (len / 2);
lazy_tag[p] = 0;
}
void push_down2(ll p, ll len)
{
mark_m[p << 1] *= mark_m[p];
mark_m[p << 1 | 1] *= mark_m[p];
tree[p << 1] = tree[p << 1] * mark_m[p];
tree[p << 1 | 1] = tree[p << 1 | 1] * mark_m[p];
mark_m[p] = 1;
}
void upd_a(ll nl, ll nr, ll p, ll l, ll r, ll add)
{
if(nr < l || nl > r) return;
else if(l <= nl && nr <= r)
{
tree[p] += add * (nr - nl + 1);
//tree[p] %= m;
if(nl < nr)
lazy_tag[p] += add;
}else
{
ll mid = (nl + nr) / 2;
push_down1(p, nr - nl + 1);
upd_a(nl, mid, p << 1, l, r, add);
upd_a(mid + 1, nr, p << 1 | 1, l, r, add);
tree[p] = (tree[p << 1] + tree[p << 1 | 1]) ;
}
}
void upd_m(ll nl, ll nr, ll p, ll l, ll r, ll tim)
{
if(nr < l || nl > r) return;
else if(l <= nl && nr <= r)
{
tree[p] = (tree[p] * tim) ;
if(nl < nr) mark_m[p] *= tim;
}else
{
ll mid = (nl + nr) / 2;
push_down2(p, nr - nl + 1);
upd_m(nl, mid, p << 1, l, r, tim);
upd_m(mid + 1, nr, p << 1 | 1, l, r, tim);
tree[p] = (tree[p << 1] + tree[p << 1 | 1]) ;
}
}
ll query(ll nl, ll nr, ll p, ll l, ll r)
{
if(nr < l || nl > r) return 0;
else if(l <= nl && nr <= r)
{
return tree[p];
}else
{
ll mid = (nl + nr) / 2;
push_down2(p, nr - nl + 1);
push_down1(p, nr - nl + 1);
return (query(nl, mid, p << 1, l, r) + query(mid + 1, nr, p << 1 | 1, l, r));
}
}
int main(){
for(ll i = 0; i < 400005; ++i) mark_m[i] = 1;
read(n);
read(q);
read(m);
//cout << "test" << n << q << m << endl;
ll flag, x, y, k, ans;
for(ll i = 1; i <= n; ++i) read(a[i]);
buid(1, n, 1);
for(ll i = 0; i < q; ++i)
{
read(flag);
if(flag == 1)
{
read(x);
read(y);
read(k);
upd_m(1, n, 1, x, y, k);
}else if(flag == 2)
{
read(x);
read(y);
read(k);
upd_a(1, n, 1, x, y, k);
}else
{
read(x);
read(y);
ans = query(1, n, 1, x, y);
cout << ans % m << endl;
}
}
return 0;
}
有大佬帮忙看看吗qwq样例过了,麻烦啦orz