#include<iostream>
#define ll long long
using namespace std;
const int MAXN = 1e5 + 5;
ll a[MAXN];
ll mod;
struct tree {
ll l, r;
ll sum, lazy_mul = 1, lazy_add = 0;
}tree[4 * MAXN + 2];
void build(ll p, ll l, ll r) {
tree[p].l = l; tree[p].r = r;
if (l == r) {
tree[p].sum = a[l] % mod;
return;
}
ll mid = l + r >> 1;
build(2 * p, l, mid);
build(2 * p + 1, mid + 1, r);
tree[p].sum = tree[2 * p].sum + tree[2 * p + 1].sum;
tree[p].sum %= mod;
}
void spread(ll p) {
tree[2 * p].sum = (ll)tree[p].lazy_mul*tree[2 * p].sum + ((tree[2 * p].r - tree[2 * p].l + 1) *tree[p].lazy_add % mod) % mod;
tree[2 * p + 1].sum = (ll)tree[p].lazy_mul*tree[2 * p + 1].sum + ((tree[2 * p + 1].r - tree[2 * p + 1].l + 1)*tree[p].lazy_add % mod) % mod;
tree[2 * p].lazy_mul = (ll)tree[2 * p].lazy_mul *tree[p].lazy_mul%mod;
tree[2 * p + 1].lazy_mul = (ll)tree[2 * p + 1].lazy_mul*tree[p].lazy_mul%mod;
tree[2 * p].lazy_add = (ll)(tree[2 * p].lazy_add *tree[p].lazy_mul + tree[p].lazy_add) % mod;
tree[2 * p + 1].lazy_add = (ll)(tree[2 * p + 1].lazy_add*tree[p].lazy_mul + tree[p].lazy_add) % mod;
tree[p].lazy_mul = 1;
tree[p].lazy_add = 0;
}
void change_add(ll p, ll x, ll y, ll z) {
if (x <= tree[p].l&&y >= tree[p].r) {
tree[p].sum += z * (tree[p].r - tree[p].l + 1) % mod;
tree[p].sum %= mod;
tree[p].lazy_add += z;
tree[p].lazy_add %= mod;
return;
}
spread(p);
ll mid = tree[p].l + tree[p].r >> 1;
tree[p].sum = tree[2 * p].sum + tree[2 * p + 1].sum;
tree[p].sum %= mod;
if (x <= mid)
{
change_add(2 * p, x, y, z);
}
if (y > mid)
{
change_add(2 * p + 1, x, y, z);
}
tree[p].sum = tree[2 * p].sum + tree[2 * p + 1].sum;
tree[p].sum %= mod;
}
void change_mul(ll p, ll x, ll y, ll z) {
if (x <= tree[p].l&&y >= tree[p].r) {
tree[p].sum *= z;
tree[p].sum %= mod;
tree[p].lazy_mul *= z;
tree[p].lazy_mul %= mod;
tree[p].lazy_add *= z;
tree[p].lazy_add %= mod;
return;
}
spread(p);
ll mid = tree[p].l + tree[p].r >> 1;
if (x <= mid) {
change_mul(2 * p, x, y, z);
}
if (y > mid) {
change_mul(2 * p + 1, x, y, z);
}
tree[p].sum = tree[2 * p].sum + tree[2 * p + 1].sum;
tree[p].sum %= mod;
}
ll ask(ll p, ll x, ll y) {
if (x <= tree[p].l && y >= tree[p].r)
return tree[p].sum;
spread(p);
int mid = tree[p].l + tree[p].r >> 1;
ll ans = 0;
if (x <= mid) {
ans += ask(p * 2, x, y);
ans %= mod;
}
if (y > mid) {
ans += ask(p * 2 + 1, x, y);
ans %= mod;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
int n, m;
cin >> n >> m >> mod;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
build(1, 1, n);
while (m--) {
int choice;
int x, y, z;
cin >> choice;
if (choice == 1) {
cin >> x >> y >> z;
change_mul(1, x, y, z);
}
else if(choice==2){
cin >> x >> y >> z;
change_add(1, x, y, z);
}
else {
cin >> x >> y;
cout << ask(1, x, y) << endl;
}
}
return 0;
}