#include <iostream>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <cstring>
#define lsb(x) x & -x
using namespace std;
FILE *in, *out;
const int NMAX = 250001;
int pw[NMAX];
int aint[4 * NMAX];
int p;
void update(int pos, int val, int node, int le, int ri) {
if(le == ri)
aint[node] = val % p;
else {
int mid = (le + ri) / 2;
if(pos <= mid)
update(pos, val, node * 2, le, mid);
else
update(pos, val, node * 2 + 1, mid + 1, ri);
aint[node] = (aint[node * 2] * pw[ri - mid] + aint[node * 2 + 1]) % p;
}
}
int query(int from, int to, int node, int le, int ri) {
if(from <= le && ri <= to)
return aint[node];
int mid = (le + ri) / 2;
int ans = 0;
if(from <= mid)
ans = query(from, to, node * 2, le, mid);
if(mid < to)
ans = (ans * pw[min(ri,to) - mid] + query(from, to, node * 2 + 1, mid + 1, ri)) % p; /// mama lui de MIN
return ans;
}
void buildtree(int node, int le, int ri, const vector<int> &v) {
if(le == ri)
aint[node] = v[le];
else {
int mid = (le + ri) / 2;
buildtree(node * 2, le, mid, v);
buildtree(node * 2 + 1, mid + 1, ri, v);
aint[node] = (aint[node * 2] * pw[ri - mid] + aint[node * 2 + 1]) % p;
}
}
int main() {
in = fopen("rest.in", "r");
out = fopen("rest.out", "w");
int n, b;
fscanf(in, "%d%d%d", &n, &b, &p);
vector<int> v(n + 1, 0);
pw[0] = 1;
for(int i = 1; i <= n; i ++) {
fscanf(in, "%d", &v[i]);
pw[i] = (pw[i - 1] * b) % p;
}
buildtree(1, 1, n, v);
int m;
fscanf(in, "%d", &m);
for(int i = 1; i <= m; i ++) {
int type, x, y;
fscanf(in, "%d%d%d", &type, &x, &y);
if(type == 1)
update(x, y, 1, 1, n);
if(type == 2)
fprintf(out, "%d\n", query(x, y, 1, 1, n));
}
return 0;
}