RT
#include <bits/stdc++.h>
using namespace std;
#define reg register
#define int long long
typedef long long ll;
#define IT set<node>::iterator
inline char nc () { //fread??
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread (buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read () {
register int x(0), f(1); char ch = getchar ();
while (ch < '0' || ch > '9') {if (ch == '-') f = ~f +1; ch = getchar ();}
while (ch >= '0' && ch <= '9') {x = (x<<3) + (x<<1) + (ch^48); ch = getchar ();}
return x * f;
}
struct node {
int l, r;
mutable int val;
node (int _l, int _r = -1, int _val = 0):l(_l), r(_r), val(_val){}
inline bool operator < (const node &odt) const {
return l < odt.l;
}
};
set <node> tr;
int n, m, x;
int seed, vmax;
int mod = 1e9+7;
inline int rnd() {
ll ret=seed;
seed=(seed*7+13)%mod;
return ret;
}
inline IT split (int pos) {
reg IT iser = tr.lower_bound (node(pos));
if (iser != tr.end () && iser->l == pos) return iser;
iser--;
reg int nl = iser->l, nr = iser->r, nval = iser->val;
tr.erase (iser);
tr.insert (node (nl, pos-1, nval));
return tr.insert (node (pos, nr, nval)).first;
}
inline void assign (int l, int r, int val) {
reg IT iserr = split (r+1), iserl = split (l);
tr.erase (iserl, iserr);
tr.insert (node (l, r, val));
return ;
}
inline void add (int l, int r, int v) {
reg IT iserr = split (r+1), iserl = split (l);
for (; iserl != iserr; ++iserl) iserl->val += v;
return ;
}
int quick_sum (int a, int b, int mod) {
ll res = 1;
ll ans = a % mod;
while (b)
{
if (b&1) res = res * ans % mod;
ans = ans * ans % mod;
b>>=1;
}
return res;
}
inline int qsum (int l, int r, int x, int y) {
reg IT iserr = split (r + 1), iserl = split (l);
int res = 0;
for (; iserl != iserr; ++iserl) {
res += (iserl->r - iserl->l + 1) * quick_sum (iserl->val, x, y)%y;
res %= y;
}
return res;
}
inline int rank (int l, int r, int k) {
static vector <pair <int, int> > v;
v.clear();
reg IT iserr = split (r + 1), iserl = split (l);
for (; iserl != iserr; ++iserl) {
v.push_back (pair <int, int> (iserl->val, iserl->r - iserl->l + 1));
}
std::sort (v.begin(), v.end());
for (reg vector <pair <int, int> >::iterator it = v.begin(); it != v.end (); ++it) {
k -= it->second;
if (k <= 0) return it->first;
}
return -1ll;
}
signed main () {
n = read (), m = read (), seed = read (), vmax = read ();
for (reg int i(1); i ^ (n+1); i = -~i) {
tr.insert (node(i, i, rnd()%vmax+1));
}
while (m--) {
ll op=(rnd()%4)+1,l=(rnd()%n)+1,r=(rnd()%n)+1,x,y;
if(l>r) swap(l,r);
if(op==1) {
x=(rnd()%vmax)+1;
add(l,r,x);
}
else if(op==2) {
x=(rnd()%vmax)+1;
assign(l,r,x);
}
else if(op==3) {
x=(rnd()%(r-l+1))+1;
printf("%lld\n",rank(l,r,x));
}
else {
x=(rnd()%vmax)+1,y=(rnd()%vmax)+1;
printf("%lld\n",qsum(l,r,x,y));
}
}
return 0;
}