#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
inline void work(void);
inline LL rnd();
class ODT {
private:
struct node {
int l, r;
mutable LL v;
node(int L, int R = -1, LL V = 0) : l(L), r(R), v(V) {}
inline bool operator < (const node& o) const {
return l < o.l;
}
};
set<node> s;
#define IT set<node>::iterator
IT split(int pos) {
auto it = s.lower_bound(node(pos));
if (it != s.end() && it->l == pos) return it;
it--;
if (pos > it->r) return s.end();
int L = it->l, R = it->r;
LL V = it->v;
s.erase(it);
s.insert(node(L, pos-1, V));
return s.insert(node(pos, R, V)).first;
}
virtual inline LL fast_pow(LL a, int x, LL y) {
LL b = 1LL;
a %= y;
while(x) {
if (x & 1)
b = (b * a) % y;
a = (a * a) % y;
x >>= 1;
}
return b;
}
public:
virtual inline void upload(int L, int R, LL val) {
s.insert(node(L, R, val));
}
virtual inline void assign(int l, int r, int val) {
split(l);
auto itr = split(r + 1), itl = split(l);
s.erase(itl, itr);
s.insert(node(l, r, val));
}
virtual inline void add(int l, int r, LL val=1) {
split(l);
auto itr = split(r + 1), itl = split(l);
for(; itl != itr; ++itl) itl->v += val;
}
virtual inline LL rank(int l, int r, int k, bool reversed=0) {
#define VIT vector<pair<LL,int> >::iterator
vector<pair<LL, int>> vp;
if (reversed) k = r - l + 2 - k;
split(l);
auto itr = split(r + 1), itl = split(l);
vp.clear();
for (; itl != itr; ++itl)
vp.push_back(pair<LL,int>(itl->v, itl->r - itl->l + 1));
sort(vp.begin(), vp.end());
for (VIT it=vp.begin(); it!=vp.end(); ++it) {
k -= it->second;
if (k <= 0) return it->first;
}
return -1;
}
virtual inline LL ex_sum(int l, int r, int ex, LL mod) {
split(l);
auto itr = split(r + 1), itl = split(l);
LL res = 0;
for(auto it = itl; itl != itr; ++itl)
res = (res + (LL)(it -> r - it -> l + 1) * fast_pow(it -> v, ex, mod)) % mod;
return res;
}
virtual inline LL sum(int l, int r) {
IT itr = split(r + 1), itl = split(l);
LL res = 0;
for(IT it = itl; itl != itr; ++itl) {
res = res + (it -> r + it -> l + 1);
}
return res;
}
inline auto performance(int l, int r) {
auto itr = split(r + 1), itl = split(l);
for (; itl != itr; ++itl) {
}
}
#undef VIT
#undef IT
} ODT;
class fast_IO {
public:
virtual inline int read() {
int x = 0, f = 1;
char s = getchar();
while (s < '0' || s > '9') {
if (s == '-') f = - f;
s = getchar();
}
while (s >= '0' && s <= '9') {
x = (x << 3) + (x << 1) + s - '0';
s = getchar();
}
return x * f;
}
virtual inline void _write(long long x) {
if (x >= 10)
_write(x / 10);
putchar(x % 10 + 48);
}
} FI;
int main(void) {
ios::sync_with_stdio(false);
std::cin.tie(0);
#if !ONLINE_JUDGE
freopen("chtholly.in", "r", stdin);
#endif
work();
return 0;
}
int seed = 0;
inline void work()
{
int n = FI.read();
int m = FI.read();
seed = FI.read();
int vmax = FI.read();
int a[n + 2];
for (int i = 0; i < n; i++)
{
a[i] = (rnd() % vmax) + 1;
ODT.upload(i, i, a[i]);
}
ODT.upload(n, n, 0);
while(m--)
{
int op = int(rnd() % 4) + 1;
int l = int(rnd() % n) + 1;
int r = int(rnd() % n) + 1;
if (l > r) swap(l,r);
LL x, y;
if (op == 3) x = rnd() % (r-l+1) + 1;
else x = rnd() % vmax + 1;
if (op == 4) y = rnd() % vmax + 1;
if (op == 1) ODT.add(l, r, LL(x));
else if (op == 2) ODT.assign(l, r, LL(x));
else if (op == 3) FI._write((LL)ODT.rank(l, r, x)), putchar('\n');
else if (op == 4) FI._write((LL)ODT.ex_sum(l, r, x, y)), putchar('\n');
}
}
inline LL rnd()
{
LL ret = seed;
seed = (seed * 7 + 13) % 1000000007;
return ret;
}