#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int __OneWan_2024 = [](){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
return 0;
}();
const int N = 50005;
i64 a[N][60];
vector<array<i64, 2>> lsp[60];
vector<int> phi, B;
int c, P;
i64 euler_phi(i64 n) {
i64 ans = n;
for (int i = 2 ; 1LL * i * i <= n ; i++) {
if (n % i == 0) {
ans = ans / i * (i - 1);
while (n % i == 0) {
n /= i;
}
}
}
if (n > 1) ans = ans / n * (n - 1);
return ans;
}
i64 qpow(i64 b, int idx) {
i64 k = lsp[idx][b % B[idx]][0] * lsp[idx][b / B[idx]][1];
if (k >= phi[idx]) {
k = k % phi[idx] + phi[idx];
}
return k;
}
i64 get(i64 x, int cnt, int idx) {
if (cnt == 0) {
if (x >= phi[idx]) {
x = x % phi[idx] + phi[idx];
}
return x;
}
if (phi[idx] == 1) {
return c ? 1 : 0;
}
return qpow(get(x, cnt - 1, idx + 1), idx);
}
struct Node {
int L, R, cnt;
i64 sum;
} tr[N << 2];
Node merge(Node &x, Node &y) {
return {x.L, y.R, min(x.cnt, y.cnt), (x.sum + y.sum) % P};
}
void pushup(int p) {
tr[p] = merge(tr[p << 1], tr[p << 1 | 1]);
}
void build(int p, int L, int R) {
if (L == R) {
tr[p] = {L, R, 0, a[L][0]};
return;
}
int mid = L + R >> 1;
build(p << 1, L, mid);
build(p << 1 | 1, mid + 1, R);
pushup(p);
}
void modify(int p, int QL, int QR) {
if (tr[p].cnt >= phi.size()) {
return;
}
if (tr[p].L == tr[p].R) {
tr[p].cnt++;
tr[p].sum = a[tr[p].L][tr[p].cnt];
return;
}
int mid = tr[p].L + tr[p].R >> 1;
if (QL <= mid) modify(p << 1, QL, QR);
if (QR >= mid + 1) modify(p << 1 | 1, QL, QR);
pushup(p);
}
i64 query(int p, int QL, int QR) {
if (QL <= tr[p].L && tr[p].R <= QR) {
return tr[p].sum % P;
}
i64 res = 0;
int mid = tr[p].L + tr[p].R >> 1;
if (QL <= mid) {
res = (res + query(p << 1, QL, QR)) % P;
}
if (QR >= mid + 1) {
res = (res + query(p << 1 | 1, QL, QR)) % P;
}
return res;
}
int main() {
int n, m;
cin >> n >> m >> P >> c;
int tP = P;
while (tP != 1) {
B.push_back(10000);
int idx = phi.size();
lsp[idx].resize(B[idx] + 1);
lsp[idx][0] = {1, 1};
for (int i = 1 ; i <= B[idx] ; i++) {
lsp[idx][i][0] = lsp[idx][i - 1][0] * c;
if (lsp[idx][i][0] >= tP) {
lsp[idx][i][0] = lsp[idx][i][0] % tP + tP;
}
}
for (int i = 1 ; i <= B[idx] ; i++) {
lsp[idx][i][1] = lsp[idx][i - 1][1] * lsp[idx][B[idx]][0];
if (lsp[idx][i][1] >= tP) {
lsp[idx][i][1] = lsp[idx][i][1] % tP + tP;
}
}
phi.push_back(tP);
tP = euler_phi(tP);
}
phi.push_back(1);
for (int i = 1 ; i <= n ; i++) {
cin >> a[i][0];
for (int j = 1 ; j <= (int) phi.size() ; j++) {
a[i][j] = get(a[i][0], j, 0) % P;
}
a[i][0] %= P;
}
build(1, 1, n);
while (m--) {
int op, L, R;
cin >> op >> L >> R;
if (op == 0) {
modify(1, L, R);
} else {
cout << query(1, L, R) << "\n";
}
}
return 0;
}