#include<iostream>
using namespace std;

#define int long long 
#define lc u << 1
#define rc u << 1 | 1 
const int N = 5 * 1e5 + 5;

int M;
struct node{
	int l, r;
	int x, ad, md;
}t[N << 2];
int a[N];

void up(int u){
	t[u].x = (t[lc].x + t[rc].x) % M;
}

void init(node &tr, int ad, int md){
	tr.x = (tr.x * md % M + (tr.r - tr.l + 1) * ad % M) % M;
	tr.md = (tr.md * md) % M;
	tr.ad = (tr.ad * md + ad) % M;
}

void down(int u){
	init(t[lc], t[u].ad, t[u].md);
	init(t[rc], t[u].ad, t[u].md);
	t[u].md = 1;
	t[u].ad = 0;
} 


void build(int u, int l, int r){
	t[u] = {l, r, 0, 0, 1};
	if(l == r){
		t[u].x = a[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(lc, l, mid);
	build(rc, mid + 1, r);
	up(u);
}

void add(int u, int l, int r, int ak, int mk){
	if(l <= t[u].l && t[u].r <= r){
		t[u].x = (t[u].x * mk % M + (t[u].r - t[u].l + 1) * ak % M) % M;
		t[u].md = (t[u].md * mk) % M;
		t[u].ad = (t[u].ad * mk % M + ak) % M;
		return;
	}
	down(u);
	int mid = (t[u].l + t[u].r) >> 1;
	if(l <= mid) add(lc, l, r, ak, mk);
	if(r > mid) add(rc, l, r, ak, mk);
	up(u);
}

int ask(int u, int l, int r){
	if(l <= t[u].l && t[u].r <= r){
		return t[u].x % M;
	}
	int mid = (t[u].l + t[u].r) >> 1;
	down(u);
	int ans = 0;
	if(l <= mid){
		ans += ask(lc, l, r);
		ans %= M;
	}
	if(r > mid){
		ans += ask(rc, l, r);
		ans %= M;
	}
	return ans % M;
}


int n, m;

signed main(){
	
	cin >> n >> m >> M;
	
	for(int i = 1;i <= n;i ++){
		cin >> a[i];
	}
	
	build(1, 1, n);
	
	for(int i = 1;i <= m;i ++){
		int op; cin >> op;
		int x, y, k;
		if(op == 1){
			cin >> x >> y >> k;
			add(1, x, y, 0, k);
		}
		if(op == 2){
			cin >> x >> y >> k;
			add(1, x, y, k, 1);
		}
		if(op == 3){
			cin >> x >> y;
			cout << ask(1, x, y) << '\n';
		}
	}
	
	return 0;
}
