import java.io.*;
public class model2 {
public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static StreamTokenizer t = new StreamTokenizer(br);
public static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static PrintWriter out = new PrintWriter(bw);
public static int nextInt() throws Exception {
t.nextToken();
return (int) t.nval;
}
public static class node {
long left, right;
long sum, add, mul;
}
public static int n, q, m;
public static node[] tree;
public static long[] num;
public static int lc(int x) {return 2 * x;}
public static int rc(int x) {return 2 * x + 1;}
public static void build(int index, int left, int right) {
tree[index] = new node();
tree[index].left = left;
tree[index].right = right;
tree[index].add = 0;
tree[index].mul = 1;
if (left == right) {
tree[index].sum = num[left] % m;
return;
}
long mid = left + (right - left) / 2;
build(lc(index), left, (int) mid);
build(rc(index), (int) (mid + 1), right);
tree[index].sum = (tree[lc(index)].sum + tree[rc(index)].sum) % m;
}
public static void pushDown(int index) {
tree[lc(index)].sum = (tree[lc(index)].sum * tree[index].mul + tree[index].add * (tree[lc(index)].right - tree[lc(index)].left + 1)) % m;
tree[rc(index)].sum = (tree[rc(index)].sum * tree[index].mul + tree[index].add * (tree[rc(index)].right - tree[rc(index)].left + 1)) % m;
tree[lc(index)].mul = (tree[lc(index)].mul * tree[index].mul) % m;
tree[rc(index)].mul = (tree[rc(index)].mul * tree[index].mul) % m;
tree[lc(index)].add = (tree[lc(index)].add * tree[index].mul + tree[index].add) % m;
tree[rc(index)].add = (tree[rc(index)].add * tree[index].mul + tree[index].add) % m;
tree[index].mul = 1;
tree[index].add = 0;
}
public static void update1(int index, int left, int right, long k) {
if (tree[index].left >= left && tree[index].right <= right) {
tree[index].sum = (tree[index].sum * k) % m;
tree[index].add = (tree[index].add * k) % m;
tree[index].mul = k;
return;
}
pushDown(index);
if (tree[lc(index)].right >= left) {
update1(lc(index), left, right, k);
}
if (tree[rc(index)].left <= right) {
update1(rc(index), left, right, k);
}
tree[index].sum = (tree[lc(index)].sum + tree[rc(index)].sum) % m;
}
public static void update2(int index, int left, int right, long k) {
if (tree[index].left >= left && tree[index].right <= right) {
tree[index].sum = (tree[index].sum + k * (tree[index].right - tree[index].left + 1)) % m;
tree[index].add = (tree[index].add + k) % m;
return;
}
pushDown(index);
if (tree[lc(index)].right >= left) {
update2(lc(index), left, right, k);
}
if (tree[rc(index)].left <= right) {
update2(rc(index), left, right, k);
}
tree[index].sum = (tree[lc(index)].sum + tree[rc(index)].sum) % m;
}
public static long search(int index, int left, int right) {
if (tree[index].left >= left && tree[index].right <= right) {
return tree[index].sum;
}
long sum = 0;
pushDown(index);
if (tree[lc(index)].right >= left) {
sum = (sum + search(lc(index), left, right)) % m;
}
if (tree[rc(index)].left <= right) {
sum = (sum + search(rc(index), left, right)) % m;
}
return sum;
}
public static void main(String[] args) throws Exception {
n = nextInt();
tree = new node[4 * n];
num = new long[n + 1];
q = nextInt();
m = nextInt();
for (int i = 1; i <= n; i += 1) {
num[i] = nextInt();
}
build(1, 1, n);
for (long i = 0; i < q; i += 1) {
int op = nextInt();
if (op == 1) {
update1(1, nextInt(), nextInt(), nextInt());
} else if (op == 2) {
update2(1, nextInt(), nextInt(), nextInt());
} else {
out.println(search(1, nextInt(), nextInt()));
}
}
out.flush();
}
}