【数论】Rust使用Miller-Rabin primality test判别素数
题目1
题目地址
https://ac.nowcoder.com/acm/contest/57677/A
代码
use std::io::{self, BufRead, Write};
fn is_prime_trivial(n: i128) -> bool {
if n <= 1 {
return false;
}
if n == 2 {
return true;
}
if n % 2 == 0 {
return false;
}
let mut i = 3;
while (i as f64) <= (n as f64).sqrt() {
if n % i == 0 {
return false;
}
i += 2;
}
true
}
fn power(mut a: i128, mut b: i128, m: i128) -> i128 {
let mut result = 1;
a %= m;
while b > 0 {
if b % 2 != 0 {
result = (result * a) % m;
}
b >>= 1;
a = (a * a) % m;
}
result
}
fn is_prime(n: i128) -> bool {
if n < 2 {
return false;
}
if n != 2 && n % 2 == 0 {
return false;
}
let s = ((n - 1) as u128).trailing_zeros() as i128;
let d = (n - 1) / 2i128.pow(s as u32);
let witnesses: [i128; 12] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37];
'next_witness: for &a in witnesses.iter().take_while(|&&x| x <= n - 1) {
let mut x = power(a, d, n);
if x == 1 || x == n - 1 {
continue;
}
for _r in 1..s {
x = power(x, 2, n);
if x == n - 1 {
continue 'next_witness;
}
}
return false;
}
true
}
// 如果正整数n等于1,返回1;n等于4,返回4;其他情况返回小于等于n的最大质数
fn solve(_n: i128) -> i128 {
if _n == 1 {
return 1;
} else if _n == 4 {
return 4;
} else {
let mut n = _n;
while !is_prime(n) {
n -= 1;
}
return n;
}
}
fn main() {
let stdin = io::stdin();
let mut lines = stdin.lock().lines();
let t: i32 = lines.next().unwrap().unwrap().trim().parse().unwrap();
let stdout = io::stdout();
let mut writer = io::BufWriter::new(stdout.lock());
for _ in 0..t {
let n: i128 = lines.next().unwrap().unwrap().trim().parse().unwrap();
// println!("n {}", is_prime(n));
let result = solve(n);
writeln!(&mut writer, "{}", result).unwrap();
}
}
题目2
题目地址
https://www.nowcoder.com/questionTerminal/74503af796574922904e3bdd3d0c7aee
代码
use std::io::{self, BufRead, Write};
fn power(mut a: i128, mut b: i128, m: i128) -> i128 {
let mut result = 1;
a %= m;
while b > 0 {
if b % 2 != 0 {
result = (result * a) % m;
}
b >>= 1;
a = (a * a) % m;
}
result
}
fn is_prime(n: i128) -> bool {
if n < 2 {
return false;
}
if n != 2 && n % 2 == 0 {
return false;
}
let s = ((n - 1) as u128).trailing_zeros() as i128;
let d = (n - 1) / 2i128.pow(s as u32);
let witnesses: [i128; 12] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37];
'next_witness: for &a in witnesses.iter().take_while(|&&x| x <= n - 1) {
let mut x = power(a, d, n);
if x == 1 || x == n - 1 {
continue;
}
for _r in 1..s {
x = power(x, 2, n);
if x == n - 1 {
continue 'next_witness;
}
}
return false;
}
true
}
fn calculate_prime_probability(mut n: i128) -> f64 {
let mut digits = Vec::new();
while n > 0 {
digits.push(n % 10);
n /= 10;
}
digits.reverse();
let mut total_primes = 0;
for (i, &digit) in digits.iter().enumerate() {
for new_digit in 1..=9 {
// if new_digit == digit as i128 {
// continue; // Same digit, skip
// }
let mut new_number = 0i128;
for (j, &d) in digits.iter().enumerate() {
new_number *= 10;
if i == j {
new_number += new_digit;
} else {
new_number += d as i128;
}
}
if is_prime(new_number) {
total_primes += 1;
}
}
}
total_primes as f64 / (digits.len() * 9) as f64
}
fn main() {
let n: i128 = io::stdin().lock().lines().next().unwrap().unwrap().trim().parse().unwrap();
let probability = calculate_prime_probability(n);
println!("{:.12}", probability);
}