using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; using static System.Console; using static System.Math; class Program { static void Main() { var n = long.Parse(ReadLine()); for (int i = 0; i < n; i++) { var x = long.Parse(ReadLine()); WriteLine(x.ToString() + " " + (MillerRabin(x) ? "1" : "0")); } } static uint[] l = new uint[] { 2, 325, 9375, 28178, 450775, 9780504, 1795265022 }; static bool MillerRabin(long n) { if (n < 2) return false; if (n % 2 == 0) return n == 2; var d = n - 1; var s = 0; while (d % 2 == 0) { s++; d >>= 1; } var dd = (u128)d; var nn = (u128)n; for (int i = 0; i < l.Length && l[i] < n; i++) { var a = l[i]; var c = true; var x = u128.ModPow(a, dd, nn); if (x == 1) c = false; for (int r = 0; r < s; r++) { if (x == nn - 1) c = false; if (!c) break; x = x * x % nn; } if (c) return false; } return true; } } public struct u128 { public ulong low; public ulong high; public static u128 MaxValue => new u128 { low = ulong.MaxValue, high = ulong.MaxValue }; public static u128 MinValue => 0; public u128(ulong h, ulong l) { low = l; high = h; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static u128 operator +(u128 l, u128 r)//片方にもう片方足して返すとなぜか遅い。JITはそっちのほうが短いのに。どうせhighとlow両方みるからin引数にする意味もない { var s = new u128 { low = l.low + r.low, high = l.high + r.high }; if (s.low < l.low) s.high++; return s; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static u128 operator -(u128 l, u128 r) { var s = new u128 { low = l.low - r.low, high = l.high - r.high }; if (s.low > l.low) s.high--; return s; } public static u128 operator *(u128 l, u128 r)//この実装がなぜか速くて抜けない。なんで { var h = l.low * r.high + l.high * r.low; var ll = l.low & 0xFFFFFFFF; var lh = l.low >> 32; var rl = r.low & 0xFFFFFFFF; var rh = r.low >> 32; var a = ll * rl; var b = ll * rh + lh * rl; var c = lh * rh; if (b < ll * rh) c += 1UL << 32; var lo = a + (b << 32); var hi = c + (b >> 32); if (lo < a) hi++; hi += h; return new u128 { low = lo, high = hi }; } public static u128 operator /(u128 l, u128 r)//var n = Min(TZC(l),TZC(r)); l >>= n; r >>= n; みたいなのはあまり意味がない { if (l < r) return 0; var m = LZC(r) - LZC(l); r <<= m; var t = (u128)1 << m; var q = (u128)0; while (m >= 0) { if (l >= r) { q |= t; l -= r; } r >>= 1; m--; t.R1(); } return q; } void R1() { if (high == 1) { high = 0; low = 1UL << 63; } else { low >>= 1; high >>= 1; } } public static u128 operator %(u128 l, u128 r) { return l - l / r * r; } public static u128 operator &(u128 l, u128 r) { return new u128 { low = l.low & r.low, high = l.high & r.high }; } public static u128 operator |(u128 l, u128 r) { return new u128 { low = l.low | r.low, high = l.high | r.high }; } public static u128 operator ^(u128 l, u128 r) { return new u128 { low = l.low ^ r.low, high = l.high ^ r.high }; } public static u128 operator <<(u128 l, int r) { r &= 0x7F; if (r >= 64) { l.high = l.low << r - 64; l.low = 0; } else if (r != 0) { l.high <<= r; l.high |= l.low >> 64 - r; l.low <<= r; } return l; } public static u128 operator >>(u128 l, int r) { r &= 0x7F; if (r >= 64) { l.low = l.high >> r - 64; l.high = 0; } else if (r != 0) { l.low >>= r; l.low |= l.high << 64 - r; l.high >>= r; } return l; } public static bool operator ==(u128 l, u128 r) { return l.low == r.low && l.high == r.high; } public static bool operator !=(u128 l, u128 r) { return l.low != r.low || l.high != r.high; } public static bool operator >(u128 l, u128 r) { if (l.high > r.high) return true; if (l.high < r.high) return false; return l.low > r.low; } public static bool operator <(u128 l, u128 r) { if (l.high < r.high) return true; if (l.high > r.high) return false; return l.low < r.low; } public static bool operator >=(u128 l, u128 r) { if (l.high > r.high) return true; if (l.high == r.high && l.low >= r.low) return true; return false; } public static bool operator <=(u128 l, u128 r) { if (l.high < r.high) return true; if (l.high == r.high && l.low <= r.low) return true; return false; } public static u128 operator ~(u128 v) { v.low = ~v.low; v.high = ~v.high; return v; } public static u128 operator +(u128 v) { return v; } public static u128 operator ++(u128 v) { return v + 1; } public static u128 operator --(u128 v) { return v - 1; } public static explicit operator u128(sbyte v) { return new u128 { low = (ulong)v }; } public static implicit operator u128(byte v) { return new u128 { low = v }; } public static explicit operator u128(short v) { return new u128 { low = (ulong)v }; } public static implicit operator u128(ushort v) { return new u128 { low = v }; } public static explicit operator u128(int v) { return new u128 { low = (ulong)v }; } public static implicit operator u128(uint v) { return new u128 { low = v }; } public static explicit operator u128(long v) { return new u128 { low = (ulong)v }; } public static implicit operator u128(ulong v) { return new u128 { low = v }; } public static explicit operator u128(BigInteger v) { var ret = new u128 { low = (ulong)v }; v >>= 64; ret.high = (ulong)v; return ret; } public static explicit operator sbyte(u128 v) { return (sbyte)(v.low & 0x7F); } public static explicit operator byte(u128 v) { return (byte)v.low; } public static explicit operator short(u128 v) { return (short)(v.low & 0x7FFF); } public static explicit operator ushort(u128 v) { return (ushort)v.low; } public static explicit operator int(u128 v) { return (int)v.low & int.MaxValue; } public static explicit operator uint(u128 v) { return (uint)v.low; } public static explicit operator long(u128 v) { return (long)v.low & long.MaxValue; } public static explicit operator ulong(u128 v) { return v.low; } public static implicit operator BigInteger(u128 v) { return (new BigInteger(v.high) << 64) | v.low; } public static u128 ModPow(u128 x, u128 n, u128 m) { var res = (u128)1; while (n != 0) { if ((n & 1) == 1) res = res * x % m; x = x * x % m; n >>= 1; } return res; } public static u128 ModPow2(u128 x, u128 n, u128 m)//要計測 { var res = (u128)1; while (n != 0) { if (n.low == 1 && n.high == 0) res = res * x % m; x = x * x % m; n >>= 1; } return res; } //Obsolate public override bool Equals(object obj) { return base.Equals(obj); } //Obsolate //Dictionaryが参照する・・・? public override int GetHashCode() { return base.GetHashCode(); } public static int LZC(u128 v) { #if NETCOREAPP if (v.high == 0) return BitOperations.LeadingZeroCount(v.low) + 64; else return BitOperations.LeadingZeroCount(v.high); } #else if (v.high == 0) return LZCu64(v.low) + 64; else return LZCu64(v.high); } static int LZCu64(ulong n) { if (n == 0) return 64; int res = 0; if (0 != (n >> (res | 32))) res |= 32; if (0 != (n >> (res | 16))) res |= 16; if (0 != (n >> (res | 8))) res |= 8; if (0 != (n >> (res | 4))) res |= 4; if (0 != (n >> (res | 2))) res |= 2; if (0 != (n >> (res | 1))) res |= 1; return 63 - res; } #endif public static int Log2(u128 v) { return 127 - LZC(v); } public static u128 RotateLeft(u128 v, int o) { return v << o | v >> 128 - o; } public static u128 RotateRight(u128 v, int o) { return v >> o | v << 128 - o; } }