#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<set> #define LL long long using namespace std; const int N = 1e5+6,mod=1e9+7; struct node{ int l,r; mutable LL v; node(int L,int R,LL V):l(L),r(R),v(V){} inline bool operator < (const node& b)const{return l<b.l;} }; set<node>s; int n,m; LL a[N],seed,vmax; inline LL Rand(){ LL ret = seed; seed = (seed*7 + 13)%mod; return ret; } ///快速幂 inline LL qpow(LL a,LL n,LL p){ LL ans=1LL;a%=p; while(n){ if(n&1)ans=ans*a%p; a=a*a%p; n>>=1; } return ANS; } typedef SET <Node> :: Iterator the IT; inline the IT Split ( int pos) { /// the position pos section into left and right two the IT IT = s.lower_bound (Node (pos, pos, . 1 )) ; IF (IT = s.end () && IT-> L == POS!) return IT; /// If you have good points directly back /// else before we find a range of this interval is L <POS interval --IT; /// this interval to a split into [L,-POS. 1] /// this interval to a split into [POS, R & lt] int L = IT-> L, R & lt IT- => R & lt ; LL = V IT-> V; s.erase (IT); s.insert (Node (L, POS - . 1 , V)); return s.insert (Node (POS, R & lt, V)) First;. } /// force applied directly to the interval number within this range all of V + inline void the Add ( int L, int R & lt, V LL) { the IT IT1 Split = (L), Split IT2 = (R & lt + . 1 ); for (; IT2 IT1 =;! ++ IT1) it1-> V + = V; } /// interval assignment inline void The assigns ( int L, int R & lt, LL V) { /// the discontinuity region to [. 1. 1--L] [L, R & lt] [R & lt +. 1, n-] the IT Split IT1 = (L), Split IT2 = (R & lt + . 1 ); /// Clear [ l, r] of the redundant interval s.erase (IT1, IT2); /// Add a new assignment section s.insert (Node (L, R & lt, V)); } /// section K of large inline void Rank ( int L, int R & lt, int K) { the IT IT1 = Split (L), Split IT2 = (R & lt + . 1 ); Vector <pair <LL, int >> T; for (; = IT2 IT1; ++ IT1) t.push_back (pair <LL,! int > (it1-> V, it1-> R & lt - it1-> L + . 1 )); Sort (t.begin (), t.end ()); LL ANS = 0 ; for (Auto IT: T) { /// convenient container-like end can be used directly to begin Auto IF (K <= it.second) { ANS=it.first; break; }else { k-=it.second; } } printf("%lld\n",ans); } inline void sum(int l,int r,int x,int p){ IT it1=split(l),it2=split(r+1); LL ans=0; for(;it1!=it2;++it1)ans=(ans+(LL)(it1->r - it1->l+1)*qpow(it1->v,x,p))%p; printf("%lld\n",ans); } int main(){ scanf("%d%d%lld%lld",&n,&m,&seed,&vmax); for(int i=1;i<=n;i++){ a[i]=Rand()%vmax+1; s.insert(node(i,i,a[i])); } s.insert(node(n+1,n+1,0)); for(int i=1;i<=m;i++){ int opt=Rand()%4+1; int l=Rand()%n+1; int r=Rand()%n+1; if(l>r)swap(l,r); int x=0,y=0; if(opt==3)x=Rand()%(r-l+1)+1; else x=Rand()%vmax+1; if(opt==4)y=Rand()%vmax+1; if(opt==1)add(l,r,x); else if (opt==2)assigns(l,r,x); else if (opt==3)Rank(l,r,x); else sum(l,r,x,y); } return 0; }