#include<cmath>
#include<cstdio>
#include<algorithm>
#define ll long long
#define N 55000
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=gc();}
while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
return x*f;
}
struct node{
int left,right,sum,cnt;bool tag;
}tree[N<<1];
int phi[31],num,tot,n,m,p,c,a[N],root,table[31][1<<17],table1[31][1<<17];
inline int c_p(int x){
int tmp=x;
for (int i=2;i<=sqrt(x);++i) {
if (x%i) continue;tmp=tmp/i*(i-1);
while(x%i==0) x/=i;
}if (x!=1) tmp/=x,tmp*=(x-1);
return tmp;
}
inline int pow(int x,int t,int mod){
int tmp=1;
for (;t;x=(ll)x*x%mod,t>>=1) if (t&1) tmp=(ll)tmp*x%mod;
return tmp;
}
inline void init(){
for (int i=0;i<=tot;++i){
int tmp=pow(c,1<<16,phi[i]);table[i][0]=table1[i][0]=1;
for (int j=1;j<(1<<16);++j){
table[i][j]=(ll)table[i][j-1]*c%phi[i];
table1[i][j]=(ll)table1[i][j-1]*tmp%phi[i];
}
}
}
inline void update(int x){
int l=tree[x].left,r=tree[x].right;tree[x].tag=1;
tree[x].sum=(tree[l].sum+tree[r].sum)%p;
if (l)tree[x].tag&=tree[l].tag;if(r) tree[x].tag&=tree[r].tag;
}
inline void build(int &x,int l,int r){
x=++num;if (l==r) {tree[x].sum=a[l];return;}
int mid=l+r>>1; build(tree[x].left,l,mid);
build(tree[x].right,mid+1,r);update(x);
}
inline int pow1(int x,int md){
return (ll)table[md][x&((1<<16)-1)]*table1[md][x>>16]%phi[md];
}
inline int calc(int x,int t){
int tmp=x;if (tmp>phi[t]) tmp=tmp%phi[t]+phi[t];
while(t--){
tmp=pow1(tmp,t);if (!tmp&&t) tmp+=phi[t];
}return tmp%phi[0];
}
inline void insert1(int x,int l,int r,int l1,int r1){
if (l1<=l&&r1>=r&&tree[x].tag) return;int mid=l+r>>1;
if (l==r) {
++tree[x].cnt;tree[x].sum=calc(a[l],tree[x].cnt);
if (tree[x].cnt==tot) tree[x].tag=1;return;
}
if (l1<=mid) insert1(tree[x].left,l,mid,l1,r1);
if (r1>mid) insert1(tree[x].right,mid+1,r,l1,r1);update(x);
}
inline int query(int x,int l,int r,int l1,int r1){
if (l1<=l&&r1>=r) return tree[x].sum;int mid=l+r>>1,tmp=0;
if (l1<=mid) tmp+=query(tree[x].left,l,mid,l1,r1);
if (r1>mid) tmp+=query(tree[x].right,mid+1,r,l1,r1);return tmp%p;
}
inline void print(int x,int l,int r){
int mid=l+r>>1;
if (tree[x].left) print(tree[x].left,l,mid);
printf("%d %d %d\n",l,r,tree[x].sum);
if (tree[x].right) print(tree[x].right,mid+1,r);
}
int main(){
//freopen("bzoj4869.in","r",stdin);
//freopen("bzoj4869.out","w",stdout);
n=read();m=read();p=read();c=read();
phi[0]=p;tot=0;while(phi[tot]-1) ++tot,phi[tot]=c_p(phi[tot-1]);phi[++tot]=1;
//for (int i=0;i<=tot;++i) printf("%d,phi[i]);puts("");
init();
for (int i=1;i<=n;++i) a[i]=read();build(root,1,n);
for (int i=1;i<=m;++i){
int op=read(),l=read(),r=read();
if(op==0) insert1(root,1,n,l,r);else printf("%d\n",query(root,1,n,l,r));
// print(root,1,n);puts("--------");
}//puts("");
return 0;
}