using System.Diagnostics; using System.Numerics; class Program { static void Main() { Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }); var n = FastIO.Long(); for (int i = 0; i < n; i++) { var x = (ulong)FastIO.Long(); Console.WriteLine($"{x} {(PrimalityTest.MillerRabin(x) ? '1' : '0')}"); } Console.Out.Flush(); } } public static class PrimalityTest { /// /// Montgomery reduction. /// /// Returns x * R^-1 (mod m), where R = 2^64. /// m must be odd. /// private static ulong MontgomeryReduction(ulong xlo, ulong xhi, ulong m, ulong mInv) { ulong q = xlo * mInv; ulong result = xhi - Math.BigMul(q, m, out _); // Add m when the subtraction underflowed. return result > xhi ? result + m : result; } /// /// Computes a^-1 (mod 2^64) for odd a. /// /// Newton iteration: /// x' = x * (2 - a*x) /// /// If y = 1 - a*x, the new error is y^2. /// Thus the number of correct bits approximately doubles /// at every iteration. /// private static ulong MultiplicativeInverse(ulong a) { Debug.Assert((a & 1) != 0); // Initial approximation. ulong x = (3 * a) ^ 2; // y = 1 - a*x ulong y = 1 - a * x; x *= 1 + y; y *= y; x *= 1 + y; y *= y; x *= 1 + y; y *= y; x *= 1 + y; return x; } /// /// Computes a * b * R^-1 (mod m), where R = 2^64. /// m must be odd. /// private static ulong MontgomeryMultiplication(ulong a, ulong b, ulong m, ulong mInv) { ulong hi = Math.BigMul(a, b, out ulong lo); return MontgomeryReduction(lo, hi, m, mInv); } /// /// Computes (a + b) mod m. /// Requires a,b < m. /// private static ulong MontgomeryAddition(ulong a, ulong b, ulong m) { ulong sum = a + b; // Either the addition overflowed, or sum >= m. return sum < a || sum >= m ? sum - m : sum; } /// /// Returns constants required for Montgomery arithmetic: /// /// modInv = m^-1 (mod 2^64) /// rMod = R mod m /// r2Mod = R^2 mod m /// /// m must be odd. /// private static (ulong modInv, ulong rMod, ulong r2Mod) MontgomeryConstants(ulong m) { ulong modInv = MultiplicativeInverse(m); // R mod m, where R = 2^64. ulong rMod = (0ul - m) % m; // Compute R^2 mod m. // // Starting from R mod m: // x <- 4R mod m // x <- x^2 repeatedly // // Five squarings give: // (4R)^(2^5) = R^(34) // // But because the Montgomery multiplication itself // contributes R^-1 at each step, the resulting value // is R^2 mod m. ulong r2Mod = MontgomeryAddition(rMod, rMod, m); r2Mod = MontgomeryAddition(r2Mod, r2Mod, m); for (int i = 0; i < 5; i++)r2Mod = MontgomeryMultiplication(r2Mod, r2Mod, m, modInv); return (modInv, rMod, r2Mod); } /// /// Computes value^exponent mod m using Montgomery multiplication. /// /// 'power' is kept in Montgomery representation: /// value * R mod m /// /// 'result' deliberately remains in ordinary representation. /// This works because MontgomeryMultiplication(normal, mont) /// returns the ordinary product. /// private static ulong ModPow(ulong value, ulong exponent, ulong m) { var (modInv, rMod, r2Mod) = MontgomeryConstants(m); // value -> value * R (mod m) ulong power = MontgomeryMultiplication(value, r2Mod, m, modInv); // Deliberately ordinary representation. ulong result = 1; while (exponent != 0) { if ((exponent & 1) != 0) // ordinary * Montgomery -> ordinary result = MontgomeryMultiplication(result, power, m, modInv); // Montgomery * Montgomery -> Montgomery power = MontgomeryMultiplication(power, power, m, modInv); exponent >>= 1; } return result; } /// /// Computes a * b mod m. /// /// Handles both odd and even moduli. /// private static ulong ModMul(ulong a, ulong b, ulong m) { if ((m & 1) != 0) return ModMulOdd(a, b, m); return ModMulEven(a, b, m); } /// /// Computes a * b mod m for odd m. /// /// Uses: /// MontMul(a,b) = abR^-1 /// /// followed by multiplication by R^2, giving abR, /// and one final Montgomery reduction implicitly through /// the second multiplication. /// private static ulong ModMulOdd(ulong a, ulong b, ulong m) { var (modInv, _, r2Mod) = MontgomeryConstants(m); ulong result = MontgomeryMultiplication(a, b, m, modInv); result = MontgomeryMultiplication(result, r2Mod, m, modInv); return result; } /// /// Computes a * b mod m for even m. /// /// Write: /// m = 2^k * oddMod /// /// Compute the product modulo both factors, then reconstruct /// the result using Garner's algorithm. /// private static ulong ModMulEven(ulong a, ulong b, ulong m) { int k = BitOperations.TrailingZeroCount(m); ulong oddMod = m >> k; ulong mask = (1ul << k) - 1; var (modInv, _, r2Mod) = MontgomeryConstants(oddMod); // -------------------------------------------------------- // Product modulo oddMod // -------------------------------------------------------- ulong hi = Math.BigMul(a, b, out ulong lo); // First Montgomery reduction: // abR^-1 mod oddMod ulong tOdd = MontgomeryReduction(lo, hi, oddMod, modInv); // Convert back: // (abR^-1) * R^2 * R^-1 = ab tOdd = MontgomeryMultiplication(tOdd, r2Mod, oddMod, modInv); // -------------------------------------------------------- // Product modulo 2^k // -------------------------------------------------------- ulong tEven = lo & mask; // -------------------------------------------------------- // Garner reconstruction // // t = tOdd + c * oddMod // // Choose c so that: // t == tEven (mod 2^k) // // c = (tEven - tOdd) * oddMod^-1 (mod 2^k) // -------------------------------------------------------- ulong c = ((tEven - tOdd) * modInv) & mask; return tOdd + c * oddMod; } /// /// Deterministic Miller-Rabin test for all 64-bit unsigned integers. /// public static bool MillerRabin(ulong value) { // 0, 1 and 2. if (value <= 2) return value == 2; // Even numbers other than 2 are composite. if ((value & 1) == 0) return false; ulong nMinusOne = value - 1; // n - 1 = d * 2^s, d odd. int s = BitOperations.TrailingZeroCount(nMinusOne); ulong d = nMinusOne >> s; // Deterministic for every 64-bit unsigned integer. ReadOnlySpan bases = [2, 325, 9375, 28178, 450775, 9780504, 1795265022]; foreach (ulong a in bases) { // a == 0 (mod n) if (a % value == 0) continue; ulong x = ModPow(a, d, value); // a^d == 1 or -1 (mod n) if (x == 1 || x == nMinusOne) continue; int i; for (i = 1; i < s; i++) { x = ModMul(x, x, value); if (x == nMinusOne) break; } if (i == s) return false; } return true; } } public static class FastIO { static Stream str = Console.OpenStandardInput(); const int size = 1024; static byte[] buffer = new byte[size]; static int ptr = size; static byte Read() { if (ptr == size) { str.Read(buffer, 0, size); ptr = 0; } return buffer[ptr++]; } public static long Long() { var c = Read(); while (c < 0x21) { c = Read(); } var n = false; if (c == '-') { n = true; c = Read(); } var ret = 0L; while (c > 0x20) { ret = ret * 10 + c - '0'; c = Read(); } return n ? -ret : ret; } }