use proconio::input; use std::io::Write; fn main() { input! { n: usize, x: [u64; n], } let mut stdout = std::io::BufWriter::new(std::io::stdout().lock()); for &x in &x { let ans = math::is_prime(x); writeln!(stdout, "{x} {}", if ans { '1' } else { '0' }).unwrap(); } } #[allow(dead_code)] mod math { pub fn is_prime(n: u64) -> bool { const WITNESS_3: [u64; 3] = [2, 7, 61]; const WITNESS_7: [u64; 7] = [2, 325, 9375, 28178, 450775, 9780504, 1795265022]; const THRESHOLD: u64 = 4_759_123_141; if n == 1 || n % 2 == 0 { return n == 2; } let witness = if n < THRESHOLD { &WITNESS_3[..] } else { &WITNESS_7[..] }; let montgomery = Montgomery::new(n); let (one, minus_one) = (montgomery.encode(1), montgomery.encode(n - 1)); let d = n >> (n - 1).trailing_zeros(); for &a in witness { if n <= a { continue; } let mut d = d; let mut y = montgomery.pow(montgomery.encode(a), d); while d != n - 1 && y != one && y != minus_one { y = montgomery.mul(y, y); d <<= 1; } if y != minus_one && d & 1 == 0 { return false; } } true } pub struct Montgomery { n: u64, n_inv: u64, r2: u64, } impl Montgomery { pub fn new(modulus: u64) -> Self { assert_eq!(modulus % 2, 1); let n = modulus; let mut n_inv = 1u64; for _ in 0..6 { n_inv = n_inv.wrapping_mul(2u64.wrapping_sub(n.wrapping_mul(n_inv))); } let r2 = ((n as u128).wrapping_neg() % (n as u128)) as u64; Self { n, n_inv, r2 } } pub fn encode(&self, x: u64) -> u64 { self.mul(x, self.r2) } pub fn reduce(&self, x: u64) -> u64 { self.mul(x, 1) } pub fn add(&self, a: u64, b: u64) -> u64 { let (sum, carry) = a.overflowing_add(b); let (sub, borrow) = sum.overflowing_sub(self.n); if !carry && borrow { sum } else { sub } } pub fn mul(&self, a: u64, b: u64) -> u64 { let c = a as u128 * b as u128; let d = self.n_inv.wrapping_mul(c as u64); let e = ((d as u128 * self.n as u128) >> 64) as u64; let (sub, borrow) = ((c >> 64) as u64).overflowing_sub(e); if borrow { sub.wrapping_add(self.n) } else { sub } } fn mul_add_unnormalized(&self, a: u64, b: u64, c: u64) -> u64 { let d = a as u128 * b as u128; let e = ((d >> 64) as u64).wrapping_add(self.n).wrapping_add(c); let f = self.n_inv.wrapping_mul(d as u64); let g = ((f as u128 * self.n as u128) >> 64) as u64; e.wrapping_sub(g) } pub fn pow(&self, lhs: u64, mut e: u64) -> u64 { let one = self.encode(1); let mut res = one; let mut pow = lhs; while e > 0 { if e & 1 == 1 { res = self.mul(res, pow); } pow = self.mul(pow, pow); e >>= 1; } res } } }