import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Scanner;
import java.util.StringTokenizer;
public class Main{
static InputReader in = new InputReader();
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static Scanner sc = new Scanner(System.in);
static int n, m;
static long p;
static class Tree{
int l, r;
long sum, plus_lazy, mul_lazy;
public Tree(int l, int r) {
this.l = l;
this.r = r;
sum = plus_lazy = 0;
mul_lazy = 1;
}
}
static Tree[] tree;
static int[] input;
static void init(int i, int l, int r) {
tree[i] = new Tree(l, r);
if(l == r) {
tree[i].sum = input[l] % p;
return;
}
int mid = (l + r) >> 1;
init(i*2, l, mid);
init(i*2+1, mid+1, r);
tree[i].sum = (tree[i*2].sum + tree[i*2+1].sum) % p;
return;
}
static void mul(int i, int l, int r, long k) {
if(tree[i].r < l || tree[i].l > r) {
return;
}
if(tree[i].l >= l && tree[i].r <= r) {
tree[i].sum = (tree[i].sum * k) % p;
tree[i].mul_lazy = (tree[i].mul_lazy * k) % p;
tree[i].plus_lazy = (tree[i].plus_lazy * k) % p;
return;
}
if(tree[i*2].r >= l) mul(i*2, l, r, k);
if(tree[i*2+1].l <= r) mul(i*2+1, l, r, k);
tree[i].sum = (tree[i << 1].sum + tree[i << 1 | 1].sum) % p;
return;
}
static void add(int i, int l, int r, long k) {
if(tree[i].r < l || tree[i].l > r) {
return;
}
if(tree[i].l >= l && tree[i].r <= r) {
tree[i].sum = (tree[i].sum + k * (tree[i].r - tree[i].l + 1)) % p;
tree[i].plus_lazy = (tree[i].plus_lazy + k) % p;
return;
}
push_down(i);
if(tree[i*2].r >= l) add(i*2, l, r, k);
if(tree[i*2+1].l <= r) add(i*2+1, l, r, k);
tree[i].sum = (tree[i << 1].sum + tree[i << 1 | 1].sum) % p;
return;
}
static void push_down(int i) {
tree[i << 1].sum = (tree[i << 1].sum * tree[i].mul_lazy + tree[i].plus_lazy * (tree[i << 1].r - tree[i << 1].l + 1) % p) % p;
tree[i << 1 | 1].sum = (tree[i << 1 | 1].sum * tree[i].mul_lazy + tree[i].plus_lazy * (tree[i << 1 | 1].r - tree[i << 1 | 1].l + 1) % p) % p;
tree[i << 1].mul_lazy = (tree[i << 1].mul_lazy * tree[i].mul_lazy) % p;
tree[i << 1 | 1].mul_lazy = (tree[i << 1 | 1].mul_lazy * tree[i].mul_lazy) % p;
tree[i << 1].plus_lazy = (tree[i << 1].plus_lazy * tree[i].mul_lazy + tree[i].plus_lazy) % p;
tree[i << 1 | 1].plus_lazy = (tree[i << 1 | 1].plus_lazy * tree[i].mul_lazy + tree[i].plus_lazy) % p;
tree[i].plus_lazy = 0;
tree[i].mul_lazy = 1;
return;
}
static long search(int i, int l, int r) {
if(tree[i].l >= l && tree[i].r <= r) {
return tree[i].sum;
}
if(tree[i].r < l || tree[i].l > r) {
return 0;
}
push_down(i);
long sum = 0;
if(tree[i << 1].r >= l) sum = (sum + search(i*2, l, r)) % p;
if(tree[i << 1 | 1].l <= r) sum = (sum + search(i*2+1, l, r)) % p;
return sum;
}
public static void main(String args[]) throws Exception{
n = in.nextInt();
m = in.nextInt();
p = in.nextLong();
input = new int[n+1];
tree = new Tree[1000007];
for(int i = 1; i <= n; i++) {
input[i] = in.nextInt();
}
init(1, 1, n);
for(int i = 1; i <= m; i++) {
int num = in.nextInt();
int x = 0;
int y = 0;
long k = 0;
if(num == 1) {
x = in.nextInt();
y = in.nextInt();
k = in.nextLong();
mul(1, x, y, k);
continue;
}
if(num == 2) {
x = in.nextInt();
y = in.nextInt();
k = in.nextLong();
add(1, x, y, k);
continue;
}
if(num == 3) {
x = in.nextInt();
y = in.nextInt();
out.println(search(1, x, y));
}
}
out.close();
}
static class InputReader{
StringTokenizer st;
BufferedReader bf;
public InputReader() {
st = null;
bf = new BufferedReader(new InputStreamReader(System.in));
}
public String next() throws IOException{
while(st == null || !st.hasMoreTokens()) {
st = new StringTokenizer(bf.readLine());
}
return st.nextToken();
}
public int nextInt() throws IOException{
return Integer.parseInt(next());
}
public long nextLong() throws IOException{
return Long.parseLong(next());
}
public double nextDouble() throws IOException{
return Double.parseDouble(next());
}
public BigDecimal nextBigDecimal() throws IOException{
return new BigDecimal(next());
}
}
}