#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <queue>
using namespace std;
#define ll long long
#define For(i, l, r) for (int i = (int)(l); i <= (int)(r); ++i)
#define in(x) x = gi()
inline int gi()
{
char tmp = getchar();
int ans = 0;
while (!isdigit(tmp))
tmp = getchar();
while (isdigit(tmp))
ans = ans * 10 + tmp - '0', tmp = getchar();
return ans;
}
const int N = 1e5 + 10;
#define LOG 58
int n, m, p, c;
int cntp;
struct Seg
{
int min, sum;
} T[N << 2];
#define ls (pos << 1)
#define rs (ls | 1)
#define mid ((l + r) >> 1)
#define lson ls, l, mid
#define rson rs, mid + 1, r
inline void Pu(int pos)
{
T[pos].min = min(T[ls].min, T[rs].min);
T[pos].sum = T[ls].sum + T[rs].sum;
while(T[pos].sum >= p) T[pos].sum -= p;
}
int A[LOG][N], Phi[N];
void Update(int pos, int l, int r, int ql, int qr)
{
if (T[pos].min >= cntp)
return;
if (l == r)
{
T[pos].min++;
T[pos].sum = A[T[pos].min][l];
return;
}
if (ql <= mid)
Update(lson, ql, qr);
if (qr > mid)
Update(rson, ql, qr);
Pu(pos);
}
int Query(int pos, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr)
{
return T[pos].sum;
}
int ans = 0;
if (ql <= mid)
ans += Query(lson, ql, qr);
if (qr > mid)
ans = 1ll * (ans + Query(rson, ql, qr)) % p;
return ans % p;
}
inline int Get(int n)
{
static int t, i, ans;
t = n, ans = n;
for (i = 2; i * i <= n; ++i)
if (t % i == 0)
{
while (!(t % i))
t /= i;
ans = ans / i * (i - 1);
}
if (t > 1)
ans = ans / t * (t - 1);
return ans;
}
int Pow1[1<<16][LOG], Pow2[1<<16][LOG];
inline int Mod(long long x, int p)
{
if (x >= p)
return x % p +p ;
return x;
}
void Pre()
{
For(i, 0, cntp)
{
Pow2[0][i] = Pow1[0][i] = 1;
For(j, 1, (1<<15)-1)
Pow1[j][i] = Mod(1ll * Pow1[j - 1][i] * c, Phi[i]);
Pow2[1][i] = Mod(1ll*Pow1[(1<<15)-1][i]*c,Phi[i]);
For(j, 2, (1<<15)-1)
Pow2[j][i] = Mod(1ll * Pow2[j - 1][i] * Pow2[1][i], Phi[i]);
}
return;
}
int Pow(int a, int b)
{
int j = a & 32767, k = a >> 15;
return Mod(1ll * Pow1[j][b] * Pow2[k][b], Phi[b]);
}
int F(int x, int a, int b)
{
if (!a)
return Mod(x, Phi[b]);
if (b == cntp)
return c ? 1 : 0;
return Pow(F(x, a - 1, b + 1), b);
}
void Build(int pos, int l, int r)
{
if (l == r)
{
T[pos].min = 0;
T[pos].sum = A[0][l];
return;
}
Build(lson), Build(rson);
Pu(pos);
}
signed main()
{
#ifdef NICEGUODONG
freopen("data.in", "r", stdin);
#endif
in(n), in(m), in(p), in(c);
Phi[0]=p;
while(Phi[cntp]>1){
int x=cntp;
Phi[++cntp]=Get(Phi[x]);
}
Phi[++cntp]=1;
Pre();
For(i, 1, n) A[0][i] = gi() ; // diff
For(i, 1, n){
For(j, 1, cntp+1)
A[j][i] = F(A[0][i], j, 0) % p;
A[0][i] %= p;
}
Build(1, 1, n);
// return 0;
For(i, 1, m)
{
int opt, l, r;
in(opt), in(l), in(r);
if (opt == 0)
Update(1, 1, n, l, r);
if (opt == 1)
{
cout << (Query(1, 1, n, l, r)) % p;
putchar('\n');
}
}
return 0;
}