#include<stdio.h>
#include<set>
using namespace std;
#include<algorithm>
#include<vector>
#define IT set < node > :: iterator
#define int long long
const int MOD = 1e9 + 7;
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& a)const
{
return l < a.l;
}
};
set < node > s;
inline IT split(int pos)
{
IT it = s.lower_bound(node(pos));
if (it != s.end() && it -> l == pos)
return it;
it --;
int l = it -> l, r = it -> r, val = it -> val;
s.erase(it);
s.insert(node(l, pos - 1, val));
return s.insert(node(pos, r, val)).first;
}
inline void bulldoze(int l, int r, int val)
{
IT itr = split(r + 1), itl = split(l);
s.erase(itl, itr);
s.insert(node(l, r, val));
}
inline void add(int l, int r, int val)
{
IT itr = split(r + 1), itl = split(l);
while (itl != itr)
itl -> val += val, itl ++;
}
inline int qpow(int a, int b, int mod)
{
int ret = 1;
while (b)
{
if (b & 1)
ret = (ret * a) % mod;
a = a * a % mod;
b >>= 1;
}
return ret;
}
inline int query1(int l, int r, int b, int mod)
{
IT itr = split(r + 1), itl = split(l);
int ret = 0;
while (itl != itr)
ret = (ret + qpow(itl -> val, b, mod) * (itl -> r - itl -> l + 1) % mod) % mod, itl ++;
return ret;
}
struct node1
{
int val, siz;
inline bool operator < (const node1& a)const
{
return val < a.val;
}
};
inline int query2(int l, int r, int k)
{
vector < node1 > v;
IT itr = split(r + 1), itl = split(l);
while (itl != itr)
v.push_back((node1){itl -> val, itl -> r - itl -> l + 1}), itl ++;
sort(v.begin(), v.end());
for (int i = 0;i < v.size();i ++)
if (v[i].siz < k)
k -= v[i].siz;
else
return v[i].val;
}
int n, m, seed, vmax;
inline void swap(int& a, int& b) {a ^= b, b ^= a, a ^= b;}
inline int rnd()
{
int ret = seed;
seed = (seed * 7 + 13) % MOD;
return ret;
}
signed main()
{
scanf("%lld%lld%lld%lld", &n, &m, &seed, &vmax);
for (int i = 1;i <= n;i ++)
s.insert(node(i, i, (rnd() % vmax) + 1));
int l, r, opt, x;
while (m --)
{
opt = rnd() % 4 + 1;
l = rnd() % n + 1;
r = rnd() % n + 1;
if (l > r)
swap(l, r);
if (opt != 3)
x = rnd() % vmax + 1;
else
x = rnd() % (r - l + 1) + 1;
if (opt == 1)
add(l, r, x);
if (opt == 2)
bulldoze(l, r, x);
if (opt == 3)
printf("%lld\n", query2(l, r, x));
if (opt == 4)
printf("%lld\n", query1(l, r, x, rnd() % vmax + 1));
}
return 0;
}