#include "bits/stdc++.h"
#define int long long
using namespace std;
const int MAXN = 1e5 + 5;
int n , q , m , a[MAXN] , t[MAXN << 2] , tag1[MAXN << 2]/*加*/ , tag2[MAXN << 2]/*乘*/ , opt , x , y , k;
int ls(int p) {return p << 1;}
int rs(int p) {return (p << 1) + 1;}
void push_up(int p)
{
t[p] = (t[ls(p)] + t[rs(p)]) % m;
return;
}
void build(int p , int l , int r)
{
tag2[p] = 1;
if (l == r) {t[p] = a[l] % m; return;}
int mid = (l + r) >> 1;
build(ls(p) , l , mid);
build(rs(p) , mid + 1 , r);
push_up(p);
return;
}
void add_tag1(int p , int l , int r , int d)
{
tag2[p] = tag2[p] * d % m;
tag1[p] = tag1[p] * d % m;
t[p] = t[p] * d % m;
return;
}
void add_tag2(int p , int l , int r , int d)
{
tag1[p] = (tag1[p] + d) % m;
t[p] = (t[p] + (r - l + 1) * d) % m;
return;
}
void push_down(int p , int l , int r)
{
if (tag2[p])
{
int mid = (l + r) >> 1;
add_tag1(ls(p) , l , mid , tag2[p]);
add_tag1(rs(p) , mid + 1 , r , tag2[p]);
tag2[p] = 1;
}
if (tag1[p])
{
int mid = (l + r) >> 1;
add_tag2(ls(p) , l , mid , tag1[p]);
add_tag2(rs(p) , mid + 1 , r , tag1[p]);
tag1[p] = 0;
}
return;
}
void update1(int x , int y , int p , int l , int r , int d)
{
if (x <= l && r <= y)
{
add_tag1(p , l , r , d);
return;
}
push_down(p , l , r);
int mid = (l + r) >> 1;
if (x <= mid) update1(x , y , ls(p) , l , mid , d);
if (y > mid) update1(x , y , rs(p) , mid + 1 , r , d);
push_up(p);
return;
}
void update2(int x , int y , int p , int l , int r , int d)
{
if (x <= l && r <= y)
{
add_tag2(p , l , r , d);
return;
}
push_down(p , l , r);
int mid = (l + r) >> 1;
if (x <= mid) update2(x , y , ls(p) , l , mid , d);
if (y > mid) update2(x , y , rs(p) , mid + 1 , r , d);
push_up(p);
return;
}
int query(int x , int y , int p , int l , int r)
{
if (x <= l && r <= y) return t[p];
push_down(p , l , r);
int mid = (l + r) >> 1 , ans = 0;
if (x <= mid) ans = (ans + query(x , y , ls(p) , l , mid)) % m;
if (y > mid) ans = (ans + query(x , y , rs(p) , mid + 1 , r)) % m;
return ans;
}
signed main()
{
cin >> n >> q >> m;
for (int i = 1 ; i <= n ; i++) cin >> a[i];
build(1 , 1 , n);
while (q--)
{
cin >> opt >> x >> y;
if (opt == 1)
{
cin >> k;
update1(x , y , 1 , 1 , n , k);
}
else if (opt == 2)
{
cin >> k;
update2(x , y , 1 , 1 , n , k);
}
else
{
cout << query(x , y , 1 , 1 , n) % m << '\n';
}
}
return 0;
}
AC on #1,#3,#4.