# include <bits/stdc++.h>
using namespace std;
# define int long long
const int N = 400005;
int T, n, q, Mod;
struct Node
{
int sum, tag_times, tag_add;
};
inline int mod_add(int a, int b)
{
return ((a % Mod + b % Mod) % Mod + Mod) % Mod;
}
inline int mod_times(int a, int b)
{
return ((a % Mod) * (b % Mod) % Mod + Mod) % Mod;
}
inline void merge(Node &c, Node a, Node b)
{
c.sum = mod_add(a.sum, b.sum);
return;
}
inline void upd_times(Node &a, int l, int r, int c)
{
a.tag_times = mod_times(a.tag_times, c);
a.tag_add = mod_times(a.tag_add, c);
a.sum = mod_times(a.sum, c);
return;
}
inline void upd_add(Node &a, int l, int r, int c)
{
a.tag_add = mod_add(a.tag_add, c);
a.sum = mod_add(c * (r - l + 1), a.sum);
return;
}
# define ls (i << 1)
# define rs (i <<1 | 1)
struct Tree
{
Node a[N];
inline void init()
{
for(int i = 1; i <= 4 * n; i++)
{
a[i].tag_add = 0;
a[i].sum = 0;
a[i].tag_times = 1;
}
return;
}
inline void down(int i, int l, int r)
{
int mid = (l + r) >> 1;
upd_times(a[ls], l, mid, a[i].tag_times);
upd_add(a[ls], l, mid, a[i].tag_add);
upd_times(a[rs], mid + 1, r, a[i].tag_times);
upd_add(a[rs], mid + 1, r, a[i].tag_add);
a[i].tag_times = 1;
a[i].tag_add = 0;
return;
}
void modify_times(int i, int l, int r, int Ql, int Qr, int x)
{
if(Ql > r || Qr < l) return;
if(Ql <= l && r <= Qr)
{
upd_times(a[i], l, r, x);
return;
}
down(i, l, r);
int mid = l + r >> 1;
modify_times(ls, l, mid, Ql, Qr, x);
modify_times(rs, mid + 1, r, Ql, Qr, x);
merge(a[i], a[ls], a[rs]);
}
void modify_add(int i, int l, int r, int Ql, int Qr, int x)
{
if(Ql > r || Qr < l) return;
if(Ql <= l && r <= Qr)
{
upd_add(a[i], l, r, x);
return;
}
down(i, l, r);
int mid = l + r >> 1;
modify_add(ls, l, mid, Ql, Qr, x);
modify_add(rs, mid + 1, r, Ql, Qr, x);
merge(a[i], a[ls], a[rs]);
}
int query(int i, int l, int r, int Ql, int Qr)
{
if(Ql > r || Qr < l) return 0;
if(Ql <= l && r <= Qr) return a[i].sum;
down(i, l, r);
int mid = l + r >> 1, ans = 0;
ans += query(ls, l, mid, Ql, Qr);
ans += query(rs, mid + 1, r, Ql, Qr);
ans %= Mod;
return ans;
}
}YJHstree;
void solve()
{
scanf("%lld%lld%lld", &n, &q, &Mod);
YJHstree.init();
for(int i = 1; i <= n; i++)
{
int x;
scanf("%lld", &x);
YJHstree.modify_add(1, 1, n, i, i, x);
}
while(q--)
{
int op, x, y, k;
scanf("%lld%lld%lld", &op, &x, &y);
if(op == 1)
{
scanf("%lld", &k);
YJHstree.modify_times(1, 1, n, x, y, k);
}
if(op == 2)
{
scanf("%lld", &k);
YJHstree.modify_add(1, 1, n, x, y, k);
}
if(op == 3)
{
printf("%lld\n", YJHstree.query(1, 1, n, x, y));
}
}
}
signed main()
{
T = 1;
while(T--)
{
solve();
}
return 0;
}