#include<bits/stdc++.h>
using namespace std;
#define IT set<node>::iterator
#define ll long long
ll n,m,seed,vmax,a[100010];
struct node{
ll l,r;
mutable ll v;
};
bool operator<(node a,node b){
return a.l<b.l;
}
set<node>odt;
IT split(ll p){
IT it=odt.lower_bound({p,0,0});
if(it!=odt.end()&&it->l==p)
return it;
node l={it->l,p-1,it->v},r={p,it->r,it->v};
odt.erase(it);
odt.insert(l);
return odt.insert(r).first;
}
void assign(ll l,ll r,ll v){
IT itr=split(r+1),itl=split(l);
odt.erase(itl,itr);
odt.erase({l,r,v});
}
void add(ll l,ll r,ll v){
IT itr=split(r+1),itl=split(l);
for(IT it=itl;it!=itr;++it)
it->v+=v;
}
struct nums{
ll cnt,val;
bool operator<(nums x){return val<x.val;}
};
ll rnk(ll l,ll r,ll x){
IT itr=split(r+1),itl=split(l);
vector<nums>v;
for(IT it=itl;it!=itr;++it)
v.push_back({it->r-it->l+1,it->v});
sort(v.begin(),v.end());
int cnt=0;
for(auto i:v){
cnt+=i.cnt;
if(cnt>=x)
return i.val;
}
}
ll qpow(ll a,ll b,ll c){
ll res=0,base=a%c;
while(b){
if(b&1)res=res*base%c;
base=base*base%c;
b>>=1;
}
return res;
}
ll cal(ll l,ll r,ll x,ll y){
IT itr=split(r+1),itl=split(l);
ll res=0;
for(IT it=itl;it!=itr;++it)
res=(((res+qpow(it->v,x,y))%y)*((it->r-it->l+1)%y))%y;
return res;
}
ll rnd(){
ll ret=seed;
seed=(seed*7+13)%1000000007;
return ret;
}
int main(){
cin>>n>>m>>seed>>vmax;
for(int i=1;i<=n;++i){
a[i]=rnd()%vmax+1;
odt.insert({i,i,a[i]});
}
while(m--){
ll op,l,r,x,y;
op=rnd()%4+1;
l=rnd()%n+1;
r=rnd()%n+1;
if(l>r)swap(l,r);
if(op==3)x=rnd()%(r-l+1)+1;
else x=(rnd()%vmax)+1;
if(op==4)y=rnd()%vmax+1;
if(op==1)add(l, r, x);
else if(op==2)assign(l,r,x);
else if(op==3)cout<<rnk(l,r,x)<<"\n";
else cout<<cal(l,r,x,y)<<"\n";
}
return 0;
}