using System; using System.IO; using System.Linq; using System.Text; using System.Collections.Generic; using System.Diagnostics; using System.Numerics; using Enu = System.Linq.Enumerable; using System.Collections; class Program { public void Solve() { //Test(); long N = Reader.Int(), S = Reader.Int(); long X = Reader.Int(), Y = Reader.Int(), Z = Reader.Int(); int Q = Reader.Int(); var table = Reader.IntTable(Q); var A = new long[(N + BitW - 1) / BitW + 1]; var tmp = new long[(MaxRange + BitW - 1) / BitW + 1]; for (int i = 0; i < N; i++) { A[i / BitW] |= (S % 2) << (i % BitW); S = (S * X + Y) % Z; } foreach (var row in table) { int fromL = row[0] - 1, len = row[1] - fromL, toL = row[2] - 1; RangeXor(A, A, fromL, toL, len); } var res = new StringBuilder(); for (int i = 0; i < N; i++) res.Append((A[i / BitW] >> (i % BitW) & 1) == 1 ? 'O' : 'E'); Console.WriteLine(res); Console.ReadLine(); } static readonly int BitW = 64; static readonly int MaxRange = (int)2e5; static long[] tmp = new long[MaxRange / BitW + 10]; static void RangeXor(long[] A, long[] B, int fromL, int toL, int len) { Func GetMask = n => n == 64 ? -1L : (1L << n) - 1; int fromR = fromL + len - 1; int ai = fromL / BitW, aleft = fromL % BitW, alast = fromR / BitW; int bleft = toL % BitW; int firstAlen = Math.Min(len, BitW - aleft); int firstBlen = Math.Min(len, BitW - bleft); int firstLen = Math.Min(firstAlen, firstBlen); int ti = 0; tmp[ti] = (A[ai] >> aleft & GetMask(firstLen)) << bleft; Show(tmp[ti]); int LBshift = bleft + firstLen; if (bleft + firstLen == BitW) { LBshift = firstAlen - firstBlen; tmp[++ti] = A[ai] >> aleft >> firstLen & GetMask(firstAlen - firstBlen); Show(tmp[ti]); } long Lmask = GetMask(BitW - LBshift); int RAshift = BitW - LBshift; long Rmask = GetMask(LBshift); for (ai++; ai < alast; ai++) { tmp[ti] |= (A[ai] & Lmask) << LBshift; Show(tmp[ti]); tmp[++ti] = A[ai] >> RAshift & Rmask; Show(tmp[ti]); } if (ai == alast) { int lastLen = fromR - ai * BitW + 1; int Llen = BitW - LBshift; long bits = A[ai] & GetMask(Math.Min(lastLen, Llen)) << LBshift; tmp[ti] |= bits; Show(tmp[ti]); if (Llen < lastLen) { tmp[++ti] = A[ai] & GetMask(lastLen - Llen); Show(tmp[ti]); } } for (int i = 0, bi = toL / BitW; i <= ti; i++, bi++) B[bi] ^= tmp[i]; } [Conditional("DEBUG")] static void Show(long bits) { //Console.WriteLine(Convert.ToString(bits, 2).PadLeft(64, '0')); } void Test() { var random = new Random(); for (int times = 1; ; times++) { if (times % 100 == 0) Console.WriteLine("times:" + times); int N = 2000000; long[] A = new long[(N + BitW - 1) / BitW]; long[] A2 = new long[A.Length]; for (int i = 0; i < A.Length; i++) { A[i] = A2[i] = -1L; } int len = random.Next(1, MaxRange + 1); int from = random.Next(A.Length * BitW - len); int to = random.Next(A.Length * BitW - len); //RangeXor(A, A, 65, 120, 30); //Console.WriteLine(Convert.ToString(A[0], 2).PadLeft(64, '0')); //Console.WriteLine(Convert.ToString(A[1], 2).PadLeft(64, '0')); //if (A.Length > 2) Console.WriteLine(Convert.ToString(A[2], 2).PadLeft(64, '0')); //Console.ReadLine(); var sw = Stopwatch.StartNew(); RangeXorNaive(A, A, from, to, len); RangeXor(A2, A2, from, to, len); for (int i = 0; i < A.Length; i++) if (A[i] != A2[i]) { Console.WriteLine("bad"); Console.WriteLine("from:" + from + " to:" + to + " len:" + len + " i:" + i); Console.WriteLine("----------------------------------------------"); Console.WriteLine("Naive:"); Console.WriteLine(Convert.ToString(A[0], 2).PadLeft(64, '0')); Console.WriteLine(Convert.ToString(A[1], 2).PadLeft(64, '0')); if (A.Length > 2) Console.WriteLine(Convert.ToString(A[2], 2).PadLeft(64, '0')); Console.WriteLine("----------------------------------------------"); Console.WriteLine("Fast:"); Console.WriteLine(Convert.ToString(A2[0], 2).PadLeft(64, '0')); Console.WriteLine(Convert.ToString(A2[1], 2).PadLeft(64, '0')); if (A2.Length > 2) Console.WriteLine(Convert.ToString(A2[2], 2).PadLeft(64, '0')); //if (to / BitW == i / BitW) Console.WriteLine("L bad"); //if ((to + len - 1) / BitW == i / BitW) Console.WriteLine("R bad"); Console.ReadLine(); break; } //Console.WriteLine(sw.ElapsedMilliseconds + "ms"); } } static void RangeXorNaive(long[] A, long[] B, int fromL, int toL, int len) { var tmp = new long[len]; for (int i = 0; i < len; i++) tmp[i] = A[(fromL + i) / BitW] >> ((fromL + i) % BitW) & 1; for (int i = 0; i < len; i++) B[(toL + i) / BitW] ^= tmp[i] << ((toL + i) % BitW); } } class Entry { static void Main() { new Program().Solve(); } } class Reader { private static TextReader reader = Console.In; private static readonly char[] separator = { ' ' }; private static readonly StringSplitOptions op = StringSplitOptions.RemoveEmptyEntries; private static string[] A = new string[0]; private static int i; private static void Init() { A = new string[0]; } public static void Set(TextReader r) { reader = r; Init(); } public static void Set(string file) { reader = new StreamReader(file); Init(); } public static bool HasNext() { return CheckNext(); } public static string String() { return Next(); } public static int Int() { return int.Parse(Next()); } public static long Long() { return long.Parse(Next()); } public static double Double() { return double.Parse(Next()); } public static int[] IntLine() { return Array.ConvertAll(Split(Line()), int.Parse); } public static int[] IntArray(int N) { return Enu.Range(0, N).Select(i => Int()).ToArray(); } public static int[][] IntTable(int H) { return Enu.Range(0, H).Select(i => IntLine()).ToArray(); } public static string[] StringArray(int N) { return Enu.Range(0, N).Select(i => Line()).ToArray(); } public static string Line() { return reader.ReadLine().Trim(); } private static string[] Split(string s) { return s.Split(separator, op); } private static string Next() { CheckNext(); return A[i++]; } private static bool CheckNext() { if (i < A.Length) return true; string line = reader.ReadLine(); if (line == null) return false; if (line == "") return CheckNext(); A = Split(line); i = 0; return true; } }