QAQ
可能有一点长,凑合看吧/fad
#pragma GCC target("sse3","sse2","sse")
#pragma GCC target("avx","sse4","sse4.1","sse4.2","ssse3")
#include<bits/stdc++.h>
using namespace std;
#define reg register
#define inf 0x7ffffff
#define IT set<node>::iterator
typedef long long TYPE;
struct node{
unsigned int l,r;
mutable TYPE v;
node(unsigned int left,unsigned int right=0,TYPE value=0);
};
bool operator<(node a,node b){
return a.l<b.l;
}
node::node(unsigned int left,unsigned int right,TYPE value){
l=left;
r=right;
v=value;
}
set<node>odt;
inline IT split(unsigned int p){
IT it=odt.lower_bound(node(p));
if(it!=odt.end()&&it->l==p)
return it;
--it;
unsigned r=it->r,l=it->l;
TYPE v=it->v;
odt.erase(it);
odt.insert(node(l,p-1,v));
return odt.insert(node(p,r,v)).first;
}
inline void assign(int l, int r, int v) {
IT itr=split(r+1),itl=split(l);
odt.erase(itl, itr);
odt.insert(node(l, r, v));
}
inline int qpow(int a,int b,long long c){
reg int ans=1,tmp=a;
while(b){
if(b&1)ans=ans*tmp%c;
tmp=tmp*tmp%c;
b>>=1;
}
return ans%c;
}
inline void add(int l,int r,int v){
IT itr=split(r+1),itl=split(l);
for(IT it=itl;it!=itr;++it)
it->v+=v;
}
inline int query1(int l,int r,int x){
IT itr=split(r+1),itl=split(l);
vector<TYPE>v;
v.clear();
for(IT it=itl;it!=itr;++it){
int tmp=it->r-it->l+1;
while(tmp--)
v.push_back(it->v);
}
sort(v.begin(),v.end());
return v[x];
}
inline unsigned long long query2(int l,int r,int x,long long y){
IT itr=split(r+1),itl=split(l);
unsigned long long ans=0;
for(IT it=itl;it!=itr;++it)
ans+=(itr->r-itl->l+1)*qpow(it->v,x,y)%y;
return ans;
}
namespace IO{
char ibuf[(1<<20)+1],*iS,*iT;
#if ONLINE_JUDGE
#define gh() (iS==iT?iT=(iS=ibuf)+fread(ibuf,1,(1<<20)+1,stdin),(iS==iT?EOF:*iS++):*iS++)
#else
#define gh() getchar()
#endif
inline long long read(){
reg char ch=gh();
reg long long x=0;
reg char t=0;
while(ch<'0'||ch>'9') t|=ch=='-',ch=gh();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=gh();
return t?-x:x;
}
inline void write(long long x) {
if(x<0)
putchar('-'), x = -x;
if(x>9)
write(x/10);
putchar(x%10+'0');
}
}
using IO::read;
using IO::write;
int n,m,s,v;
inline int rnd(){
int ret=s;
s=(s*7+13)%1000000007;
return ret;
}
int main(){
n=read();
m=read();
s=read();
v=read();
for(int i=1;i<=n;++i){
static int tmp=0;
tmp=rnd()%v+1;
odt.insert(node(i,i,(long long)tmp));
}
odt.insert(node(n+1,n+1,0));
for(int i=1;i<=m;++i){
static int l=0,r=0,x=0,y=0,op=0;
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);
else x=rnd()%v+1;
if(op==4)y=rnd()%v+1;
//Hello,world!
switch(op){
case 1:add(l,r,(long long)x);break;
case 2:assign(l,r,(long long)x);break;
case 3:write(query1(l,r,x));putchar('\n');break;
case 4:write(query2(l,r,x,(long long)y));putchar('\n');break;
}
}
return 0;
}