#include <cstdio>
#include <cassert>
#include <algorithm>
#define maxN 2048
#define INFI 0x3f3f3f3f
using namespace std;
struct skl {
int sum;
int right;
void update();
};
int N, M;
int dia[maxN];
int lst[maxN][2];
skl pool[2 * maxN * maxN];
int pool_head = 0;
inline void skl::update() {
sum = (this + 1)->sum;
if (right != INFI) sum += pool[right].sum;
}
/*
void recursive_print(skl* lista) {
if (lista == NULL) return;
static int level = -1;
++level;
printf("%3d ", lista->sum);
recursive_print(lista->left);
printf("\n ");
for (int i = 0; i < level; ++i)
printf(" ");
recursive_print(lista->right);
--level;
}
int recursive_check(skl* lista) {
if (lista->end - lista->begin == 1)
return lista->sum;
assert(lista->sum == recursive_check(lista->left) +
recursive_check(lista->right));
return lista->sum;
}
void print(skl* lista, const char* name) {
printf("=============================\n");
printf("%s:\n", name);
recursive_print(lista);
printf("\n");
recursive_check(lista);
printf("*****************************\n");
}
#define print(lista) print(lista, #lista)
*/
int query_count = 0;
int create(int* line, int begin, int end, int limit) {
++query_count;
if (begin >= limit) return INFI;
const int node = pool_head++;
if (end - begin != 1) {
const int mid = (begin + end) / 2;
create(line, begin, mid, limit); // left
pool[node].right = create(line, mid, end, limit); // right
pool[node].update();
} else {
pool[node].right = INFI;
pool[node].sum = line[begin];
}
return node;
}
int query(int lista, int count) {
int sum = 0;
int begin = 0;
int end = N;
while (lista != INFI) {
++query_count;
const int mid = (begin + end) / 2;
if (begin >= count) break;
if (mid <= count) {
if (end - begin > 1)
sum += pool[lista+1].sum;
begin = mid;
lista = pool[lista].right;
} else {
end = mid;
++lista;
}
}
return sum;
}
void mix(int first, int second, int begin, int end, int count) {
++query_count;
// assert(first->begin == second->begin);
// assert(first->end == second->end);
if (end <= count) {
// intervalul e in partea stanga a liniei
return;
}
const int mid = (begin + end) / 2;
if (mid >= count) {
// partea dreapta trebuie intershimbata
mix(first + 1, second + 1, begin, mid, count);
swap(pool[first].right, pool[second].right);
} else {
mix(pool[first].right, pool[second].right, mid, end, count);
}
// facem update la suma
pool[first].update();
pool[second].update();
}
void recursive_print_square(int lista, int begin, int end, bool dir) {
if (lista == INFI) return;
if (end - begin == 1) {
printf("%d ", pool[lista].sum);
return;
} else {
const int mid = (begin + end) / 2;
if (dir) {
recursive_print_square(pool[lista].right, mid, end, dir);
recursive_print_square(lista + 1, begin, mid, dir);
} else {
recursive_print_square(lista + 1, begin, mid, dir);
recursive_print_square(pool[lista].right, mid, end, dir);
}
}
}
void print_square() {
for (int i = 0; i < N; ++i) {
if (i != 0)
recursive_print_square(lst[i][0], 0, N, true);
printf("%d ", dia[i]);
if (i != N-1)
recursive_print_square(lst[i][1], 0, N, false);
printf("\n");
}
}
int main() {
freopen("eprubeta.in", "rt", stdin);
freopen("eprubeta.out", "wt", stdout);
scanf("%d %d", &N, &M);
int X, A, B;
scanf("%d %d %d", &X, &A, &B);
for (int i = 0; i < N; ++i) {
int line[maxN];
for (int j = 0; j < N; ++j)
line[j] = ((i + A) * (j + B) / 4) % X;
dia[i] = line[i];
lst[i][0] = lst[i][1] = INFI;
// creem prima lista (stanga)
if (i != 0) {
int temp[maxN] = { 0 };
copy(line, line + i, temp);
reverse(temp, temp + i);
lst[i][0] = create(temp, 0, N, i);
}
// creem a doua lista (dreapta)
if (i != N-1) {
int temp[maxN] = { 0 };
copy(line + i + 1, line + N, temp);
lst[i][1] = create(temp, 0, N, N - i - 1);
}
}
fprintf(stderr, "pool_head = %d\n", pool_head);
for (int i = 0; i < M; ++i) {
int o, a, b;
scanf("%d %d %d", &o, &a, &b);
// verificam conditiile
assert(0 <= a && a < N);
assert(0 <= b && b < N);
assert(o == 1 || o == 2);
assert(a <= b);
// executam operatiile
if (o == 1) {
int l = b-a+1;
for (int j = 0; j < l-1; ++j) {
mix(lst[a+j][1], lst[b-j][0], 0, N, l-j-1);
swap(lst[a+j][1], lst[b-j][0]);
}
reverse(dia + a, dia + b + 1);
} else {
// interogare
int sum = 0;
for (int j = a; j <= b; ++j) {
sum += dia[j];
if (j > a) sum += query(lst[j][0], j - a);
if (j < b) sum += query(lst[j][1], b - j);
}
printf("%d\n", sum);
}
}
fprintf(stderr, "qc = %d\n", query_count);
unsigned int result = 0;
for (int i = 0; i < N; ++i) {
unsigned int sum = 0;
sum += dia[i];
if (i != 0) sum += pool[lst[i][0]].sum;
if (i != N-1) sum += pool[lst[i][1]].sum;
result += sum * sum * (i + 1);
}
printf("%u\n", result);
return 0;
}