#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 1e5 + 7;
int n, m, mod, flag, x, y, k, sum[MAXN];
struct Tree{
struct node {int sum, add, mu; }t[4 * MAXN];
inline int ls(int x) {return x << 1;}
inline int rs(int x) {return x << 1 | 1;}
inline void push_up(int p) {t[p].sum = (t[ls(p)].sum + t[rs(p)].sum)%mod;}
inline void f(int l, int r, int p, int add, int mu) {
t[p].sum = (t[p].sum * mu + (r - l + 1) * add) % mod;
t[p].mu = t[p].mu * mu % mod;
t[p].add = (t[p].add * mu + add) % mod;
}
inline void push_down(int l,int r, int p) {
int m = l + r >> 1;
f(1, m, ls(p), t[p].add, t[p].mu);
f(m + 1, r, rs(p), t[p].add, t[p].mu);
t[p].add = 0, t[p].mu = 1;
}
inline void build(int l, int r, int p) {
t[p].add = 0, t[p].mu = 1;
if(l == r) {
t[p].sum = sum[l];
return ;
}
int m = l + r >> 1;
build(l, m, ls(p));
build(m + 1, r, rs(p));
push_up(p);
}
inline void add(int L, int R, int l, int r, int k, int p) {
if(r < L || R < l) return ;
if(L <= l && R >= r) {
t[p].add = (t[p].add + k) % mod;
t[p].sum = (t[p].sum + (r - l + 1) * k) % mod;
return ;
}
push_down(l, r, p);
int m = l + r >> 1;
if(L <= m) add(L, R, l, m, k, ls(p));
if(R > m) add(L, R, m + 1, r, k, rs(p));
push_up(p);
}
inline void mu(int L, int R, int l, int r, int k, int p) {
if(r < L || R < l) return ;
if(L <= l && R >= r) {
t[p].add = t[p].add * k % mod;
t[p].mu = t[p].mu * k % mod;
t[p].sum = (t[p].sum * k) % mod;
return ;
}
push_down(l, r, p);
int m = l + r >> 1;
if(L <= m) mu(L, R, l, m, k, ls(p));
if(R > m) mu(L, R, m + 1, r, k, rs(p));
push_up(p);
}
inline int query(int L, int R, int l, int r,int p) {
if(r < L || R < l) return 0;
if(L <= l && R >= r) return t[p].sum;
push_down(l, r, p);
int ans = 0, m = l + r >> 1;
if(L <= m) ans = (ans + query(L, R, l, m, ls(p)))%mod;
if(R > m) ans = (ans + query(L, R, m + 1, r, rs(p)))%mod;
return ans;
}
}tree;
signed main() {
scanf("%lld%lld%lld", &n, &m, &mod);
for (int i = 1; i <= n; i++) scanf("%lld", sum + i);
tree.build(1, n ,1);
for (int i = 1; i <= m; i++) {
scanf("%lld%lld%lld", &flag, &x, &y);
if(flag == 3) {
printf("%lld\n", tree.query(x, y, 1, n, 1));
}else if(flag == 1) {
scanf("%lld", &k);
tree.mu(x, y, 1, n, k, 1);
}else if(flag == 2) {
scanf("%lld", &k);
tree.add(x, y, 1, n, k, 1);
}
}
return 0;
}