結果
| 問題 |
No.8030 ミラー・ラビン素数判定法のテスト
|
| ユーザー |
|
| 提出日時 | 2024-12-09 22:46:01 |
| 言語 | Rust (1.83.0 + proconio) |
| 結果 |
AC
|
| 実行時間 | 228 ms / 9,973 ms |
| コード長 | 2,994 bytes |
| コンパイル時間 | 12,756 ms |
| コンパイル使用メモリ | 402,796 KB |
| 実行使用メモリ | 6,820 KB |
| 最終ジャッジ日時 | 2024-12-09 22:46:15 |
| 合計ジャッジ時間 | 13,424 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 10 |
ソースコード
pub struct ModuloU32 {
pub modulo: u32, // m < 2 ** 31
}
impl ModuloU32 {
pub fn new(modulo: u32) -> Self {
assert!(modulo < 1 << 31);
Self { modulo }
}
pub fn add(&self, a: u32, b: u32) -> u32 {
let t = a + b;
if t < self.modulo {
t
} else {
t - self.modulo
}
}
pub fn sub(&self, a: u32, b: u32) -> u32 {
let (t, f) = a.overflowing_sub(b);
if !f {
t
} else {
t.wrapping_add(self.modulo)
}
}
pub fn mul(&self, a: u32, b: u32) -> u32 {
((a as u64 * b as u64) % self.modulo as u64) as u32
}
}
pub struct ModuloU64 {
pub modulo: u64, // m < 2 ** 63
}
impl ModuloU64 {
pub fn new(modulo: u64) -> Self {
assert!(modulo < 1 << 63);
Self { modulo }
}
pub fn add(&self, a: u64, b: u64) -> u64 {
let t = a + b;
if t < self.modulo {
t
} else {
t - self.modulo
}
}
pub fn sub(&self, a: u64, b: u64) -> u64 {
let (t, f) = a.overflowing_sub(b);
if !f {
t
} else {
t.wrapping_add(self.modulo)
}
}
pub fn mul(&self, a: u64, b: u64) -> u64 {
((a as u128 * b as u128) % self.modulo as u128) as u64
}
pub fn pow(&self, a: u64, mut n: usize) -> u64 {
let mut res = 1;
let mut x = a;
while n > 0 {
if n % 2 == 1 {
res = self.mul(res, x);
}
x = self.mul(x, x);
n /= 2;
}
res
}
}
/// Returns:
/// if n is prime number:
/// true
/// else:
/// false
///
/// Algorithm:
/// Miller-Rabin
///
/// References:
/// - [Deterministic variants of the Miller-Rabin primality test. Miller-Rabin SPRP bases records](https://miller-rabin.appspot.com/)
/// - [64bit数の素数判定](https://zenn.dev/mizar/articles/791698ea860581)
pub fn is_prime(n: u64) -> bool {
if n == 0 || n == 1 {
return false;
}
if n == 2 {
return true;
}
if n % 2 == 0 {
return false;
}
let s = (n - 1).trailing_zeros();
let d = (n - 1) >> s;
let modulo = ModuloU64::new(n);
let maybe_prime = |a| {
let a = a % n;
if a == 0 {
return true;
}
let mut ad = modulo.pow(a, d as usize);
if ad == 1 || ad == n - 1 {
return true;
}
for _ in 1..s {
ad = modulo.pow(ad, 2);
if ad == n - 1 {
return true;
}
}
false
};
[2, 325, 9375, 28178, 450775, 9780504, 1795265022]
.into_iter()
.all(maybe_prime)
}
use proconio::input;
fn main() {
input! {
q: u64,
}
for _ in 0..q {
input! {
n: u64,
}
println!("{} {}", n, if is_prime(n) { 1 } else { 0 });
}
}