#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/trie_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
/* freopen("k.in", "r", stdin);
freopen("k.out", "w", stdout); */
// clock_t c1 = clock();
// std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
mt19937 rnd(time(NULL));
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define ls ((x) << 1)
#define rs ((x) << 1 + 1)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<ll, ll> PLL;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 2e6 + 7;
const ll MAXM = 4e5 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-7;
const double pi = acos(-1.0);
struct node
{
    int l, r;
    mutable ll v;
    node(int L, int R = -1, ll V = 0) { l = L, r = R, v = V; }
    friend bool operator<(const node &x, const node &y)
    {
        return x.l < y.l;
    }
};
int a[MAXN];

ll quick_pow(ll a, ll b, ll mod)
{
    ll ans = 1;
    while (b)
    {
        if (b & 1)
            ans = (1LL * ans * a) % mod;
        a = (1LL * a * a) % mod;
        b >>= 1;
    }
    return ans;
}
struct Chtholly_Tree
{
    set<node> s;
    void init() { s.clear(); }
    void insert_(node x) { s.insert(x); }
    auto split(int pos) //将含有pos位置的结点拆分成[l,pos-1]和[pos,r],返回值为后半段的迭代器
    {
        auto it = s.lower_bound(node(pos));
        if (it != s.end() && it->l == pos)
            return it;
        --it;
        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;
    }
    void assign(int l, int r, ll val = 0) //[l,r+1)区间推平为一段
    {
        auto itl = split(l), itr = split(r + 1);
        s.erase(itl, itr);
        s.insert(node(l, r, val));
    }
    void add(int l, int r, ll val = 1) //区间加
    {
        auto itl = split(l), itr = split(r + 1);
        for (; itl != itr; ++itl)
            itl->v += val;
    }
    ll rank(int l, int r, int k) //区间第k小
    {
        vector<pair<ll, int>> vp;
        auto itl = split(l), itr = split(r + 1);
        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 (auto i : vp)
        {
            k -= i.second;
            if (k <= 0)
                return i.first;
        }
        return -1LL;
    }
    ll sum(int l, int r, int ex, int mod) //区间幂次和
    {
        auto itl = split(l), itr = split(r + 1);
        ll res = 0;
        for (; itl != itr; itl++)
            res = (res + (ll)(itl->r - itl->l + 1) * quick_pow(itl->v, ll(ex), ll(mod)) % mod) % mod;
        return res;
    }
} T;
int n, m;
ll seed, vmax;
ll giverand()
{
    ll ret = seed;
    seed = (seed * 7 + 13) % MOD;
    return ret;
}
int main()
{
    while (~scanf("%d%d%lld%lld", &n, &m, &seed, &vmax))
    {
        T.init();
        for (int i = 1; i <= n; i++)
        {
            a[i] = (giverand() % vmax) + 1;
            T.insert_(node(i, i, a[i]));
        }
        T.insert_(node(n + 1, n + 1, 0));
        for (int i = 1; i <= m; i++)
        {
            int x, y;
            int op = int(giverand() % 4) + 1;
            int l = int(giverand() % n) + 1;
            int r = int(giverand() % n) + 1;
            if (l > r)
                swap(l, r);
            if (op == 3)
                x = (giverand() % (r - l + 1)) + 1;
            else
                x = (giverand() % vmax) + 1;
            if (op == 4)
                y = (giverand() % vmax) + 1;

            if (op == 1)
                T.add(l, r, ll(x));
            else if (op == 2)
                T.assign(l, r, ll(x));
            else if (op == 3)
                printf("%lld\n", T.rank(l, r, x));
            else
                printf("%lld\n", T.sum(l, r, x, y));
        }
    }
    return 0;
}
