#include <bits/stdc++.h>   using namespace std;   int n, m, seed, vmax;   const int mod = 1e9 + 7;   int rnd() {     int rlt = seed;     seed = (1ll * seed * 7 + 13) % mod;     return rlt;   }   int expmod(int a, int b, int P) {     int rlt = 1;     while (b) {       if (b & 1) rlt = 1ll * a * rlt % P;       a = 1ll * a * a % P;       b >>= 1;     }     return rlt;   }   long long a[101010], b[101010];   int op, le, ri, x, y;   void get_query() {     op = (rnd() % 4) + 1;     le = (rnd() % n) + 1;     ri = (rnd() % n) + 1;     if (le > ri) swap(le, ri);     if (op == 3)       x = (rnd() % (ri - le + 1)) + 1;     else       x = (rnd() % vmax) + 1;     if (op == 4) y = (rnd() % vmax) + 1;   }   void put_query() {     printf( %d %d %d %d , op, le, ri, x);     if (op == 4)       printf(  %d n , y);     else       puts(  );   }   long long add[101010 << 2], to[101010 << 2];   void refresh(int id) {     if (add[id] && to[id] != -1) to[id] += add[id], add[id] = 0;   }   void push_down(int id) {     refresh(id);     if (to[id] != -1) {       to[id << 1] = to[id];       add[id << 1] = 0;       to[(id << 1) ^ 1] = to[id];       add[(id << 1) ^ 1] = 0;     } else {       add[id << 1] += add[id];       add[(id << 1) ^ 1] += add[id];       add[id] = 0;     }   }   void build(int L, int R, int id) {     if (L == R) {       to[id] = a[L];       return;     }     int mid = (L + R) >> 1;     build(L, mid, id << 1);     build(mid + 1, R, (id << 1) ^ 1);   }   void update(int le, int ri, int d, int L, int R, int id) {     if (le > R || L > ri) return;     if (le <= L && R <= ri) {       refresh(id);       if (to[id] != -1) {         to[id] += d;         return;       }       add[id] += d;       return;     }     int mid = (L + R) >> 1;     push_down(id);     to[id] = -1;     update(le, ri, d, L, mid, id << 1);     update(le, ri, d, mid + 1, R, (id << 1) ^ 1);   }   void change(int le, int ri, int d, int L, int R, int id) {     if (le > R || L > ri) return;     if (le <= L && R <= ri) {       refresh(id);       add[id] = 0;       to[id] = d;       return;     }     int mid = (L + R) >> 1;     push_down(id);     to[id] = -1;     change(le, ri, d, L, mid, id << 1);     change(le, ri, d, mid + 1, R, (id << 1) ^ 1);   }   int query(int le, int ri, int x, int y, int L, int R, int id) {     if (le > R || L > ri) return 0;     if (to[id] != -1) {       refresh(id);       int len = min(R, ri) - max(L, le) + 1;       return (int)((1ll * expmod(to[id] % y, x, y) * len) % y);     }     int mid = (L + R) >> 1;     push_down(id);     to[id] = -1;     int ans1 = query(le, ri, x, y, L, mid, id << 1);     int ans2 = query(le, ri, x, y, mid + 1, R, (id << 1) ^ 1);     return (ans1 + ans2) % y;   }   priority_queue<pair<long long, int> > pq;   void calc(int le, int ri, int L, int R, int id) {     if (le > R || L > ri) return;     if (to[id] != -1) {       refresh(id);       int len = min(R, ri) - max(L, le) + 1;       pq.push(make_pair(to[id], len));       return;     }     int mid = (L + R) >> 1;     push_down(id);     to[id] = -1;     calc(le, ri, L, mid, id << 1);     calc(le, ri, mid + 1, R, (id << 1) ^ 1);   }   int main() {     scanf( %d %d %d %d , &n, &m, &seed, &vmax);     for (int i = 1; i <= n; i++) a[i] = (rnd() % vmax) + 1;     memset(to, -1, sizeof to);     build(1, n, 1);     while (m--) {       get_query();       if (op == 1) {         update(le, ri, x, 1, n, 1);       } else if (op == 2) {         change(le, ri, x, 1, n, 1);       } else if (op == 3) {         while (!pq.empty()) pq.pop();         calc(le, ri, 1, n, 1);         int tot = 0;         x = ri - le + 1 - x;         pair<long long, int> tmp;         while (1) {           tmp = pq.top();           x -= tmp.second;           if (x < 0) {             printf( %I64d n , tmp.first);             break;           }           pq.pop();         }       } else {         int ans = 0;         ans = query(le, ri, x, y, 1, n, 1);         printf( %d n , ans);       }     }     return 0;   }