結果
問題 | No.1728 [Cherry 3rd Tune] Bullet |
ユーザー |
|
提出日時 | 2021-10-29 22:39:58 |
言語 | Rust (1.83.0 + proconio) |
結果 |
AC
|
実行時間 | 2 ms / 2,000 ms |
コード長 | 9,828 bytes |
コンパイル時間 | 13,236 ms |
コンパイル使用メモリ | 384,232 KB |
実行使用メモリ | 6,820 KB |
最終ジャッジ日時 | 2024-10-07 12:18:43 |
合計ジャッジ時間 | 14,477 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 27 |
コンパイルメッセージ
warning: unused import: `BufWriter` --> src/main.rs:5:22 | 5 | use std::io::{Write, BufWriter}; | ^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default warning: unused import: `Write` --> src/main.rs:5:15 | 5 | use std::io::{Write, BufWriter}; | ^^^^^
ソースコード
#[allow(unused_imports)]use std::cmp::*;#[allow(unused_imports)]use std::collections::*;use std::io::{Write, BufWriter};// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8macro_rules! input {($($r:tt)*) => {let stdin = std::io::stdin();let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));let mut next = move || -> String{bytes.by_ref().map(|r|r.unwrap() as char).skip_while(|c|c.is_whitespace()).take_while(|c|!c.is_whitespace()).collect()};input_inner!{next, $($r)*}};}macro_rules! input_inner {($next:expr) => {};($next:expr,) => {};($next:expr, $var:ident : $t:tt $($r:tt)*) => {let $var = read_value!($next, $t);input_inner!{$next $($r)*}};}macro_rules! read_value {($next:expr, ( $($t:tt),* )) => { ($(read_value!($next, $t)),*) };($next:expr, [ $t:tt ; $len:expr ]) => {(0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()};($next:expr, $t:ty) => ($next().parse::<$t>().expect("Parse error"));}/// Verified by https://atcoder.jp/contests/abc198/submissions/21774342mod mod_int {use std::ops::*;pub trait Mod: Copy { fn m() -> i64; }#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]pub struct ModInt<M> { pub x: i64, phantom: ::std::marker::PhantomData<M> }impl<M: Mod> ModInt<M> {// x >= 0pub fn new(x: i64) -> Self { ModInt::new_internal(x % M::m()) }fn new_internal(x: i64) -> Self {ModInt { x: x, phantom: ::std::marker::PhantomData }}pub fn pow(self, mut e: i64) -> Self {debug_assert!(e >= 0);let mut sum = ModInt::new_internal(1);let mut cur = self;while e > 0 {if e % 2 != 0 { sum *= cur; }cur *= cur;e /= 2;}sum}#[allow(dead_code)]pub fn inv(self) -> Self { self.pow(M::m() - 2) }}impl<M: Mod, T: Into<ModInt<M>>> Add<T> for ModInt<M> {type Output = Self;fn add(self, other: T) -> Self {let other = other.into();let mut sum = self.x + other.x;if sum >= M::m() { sum -= M::m(); }ModInt::new_internal(sum)}}impl<M: Mod, T: Into<ModInt<M>>> Sub<T> for ModInt<M> {type Output = Self;fn sub(self, other: T) -> Self {let other = other.into();let mut sum = self.x - other.x;if sum < 0 { sum += M::m(); }ModInt::new_internal(sum)}}impl<M: Mod, T: Into<ModInt<M>>> Mul<T> for ModInt<M> {type Output = Self;fn mul(self, other: T) -> Self { ModInt::new(self.x * other.into().x % M::m()) }}impl<M: Mod, T: Into<ModInt<M>>> AddAssign<T> for ModInt<M> {fn add_assign(&mut self, other: T) { *self = *self + other; }}impl<M: Mod, T: Into<ModInt<M>>> SubAssign<T> for ModInt<M> {fn sub_assign(&mut self, other: T) { *self = *self - other; }}impl<M: Mod, T: Into<ModInt<M>>> MulAssign<T> for ModInt<M> {fn mul_assign(&mut self, other: T) { *self = *self * other; }}impl<M: Mod> Neg for ModInt<M> {type Output = Self;fn neg(self) -> Self { ModInt::new(0) - self }}impl<M> ::std::fmt::Display for ModInt<M> {fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {self.x.fmt(f)}}impl<M: Mod> ::std::fmt::Debug for ModInt<M> {fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {let (mut a, mut b, _) = red(self.x, M::m());if b < 0 {a = -a;b = -b;}write!(f, "{}/{}", a, b)}}impl<M: Mod> From<i64> for ModInt<M> {fn from(x: i64) -> Self { Self::new(x) }}// Finds the simplest fraction x/y congruent to r mod p.// The return value (x, y, z) satisfies x = y * r + z * p.fn red(r: i64, p: i64) -> (i64, i64, i64) {if r.abs() <= 10000 {return (r, 1, 0);}let mut nxt_r = p % r;let mut q = p / r;if 2 * nxt_r >= r {nxt_r -= r;q += 1;}if 2 * nxt_r <= -r {nxt_r += r;q -= 1;}let (x, z, y) = red(nxt_r, r);(x, y - q * z, z)}} // mod mod_intmacro_rules! define_mod {($struct_name: ident, $modulo: expr) => {#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]struct $struct_name {}impl mod_int::Mod for $struct_name { fn m() -> i64 { $modulo } }}}const MOD: i64 = 1_000_000_007;define_mod!(P, MOD);type MInt = mod_int::ModInt<P>;// https://judge.yosupo.jp/submission/5155mod pollard_rho {/// binary gcdpub fn gcd(mut x: i64, mut y: i64) -> i64 {if y == 0 { return x; }if x == 0 { return y; }let k = (x | y).trailing_zeros();y >>= k;x >>= x.trailing_zeros();while y != 0 {y >>= y.trailing_zeros();if x > y { let t = x; x = y; y = t; }y -= x;}x << k}fn add_mod(x: i64, y: i64, n: i64) -> i64 {let z = x + y;if z >= n { z - n } else { z }}fn mul_mod(x: i64, mut y: i64, n: i64) -> i64 {assert!(x >= 0);assert!(x < n);let mut sum = 0;let mut cur = x;while y > 0 {if (y & 1) == 1 { sum = add_mod(sum, cur, n); }cur = add_mod(cur, cur, n);y >>= 1;}sum}fn mod_pow(x: i64, mut e: i64, n: i64) -> i64 {let mut prod = if n == 1 { 0 } else { 1 };let mut cur = x % n;while e > 0 {if (e & 1) == 1 { prod = mul_mod(prod, cur, n); }e >>= 1;if e > 0 { cur = mul_mod(cur, cur, n); }}prod}pub fn is_prime(n: i64) -> bool {if n <= 1 { return false; }let small = [2, 3, 5, 7, 11, 13];if small.iter().any(|&u| u == n) { return true; }if small.iter().any(|&u| n % u == 0) { return false; }let mut d = n - 1;let e = d.trailing_zeros();d >>= e;// https://miller-rabin.appspot.com/let a = [2, 325, 9375, 28178, 450775, 9780504, 1795265022];a.iter().all(|&a| {if a % n == 0 { return true; }let mut x = mod_pow(a, d, n);if x == 1 { return true; }for _ in 0..e {if x == n - 1 {return true;}x = mul_mod(x, x, n);if x == 1 { return false; }}x == 1})}fn pollard_rho(n: i64, c: &mut i64) -> i64 {// An improvement with Brent's cycle detection algorithm is performed.// https://maths-people.anu.edu.au/~brent/pub/pub051.htmlif n % 2 == 0 { return 2; }loop {let mut x: i64; // tortoiselet mut y = 2; // harelet mut d = 1;let cc = *c;let f = |i| add_mod(mul_mod(i, i, n), cc, n);let mut r = 1;// We don't perform the gcd-once-in-a-while optimization// because the plain gcd-every-time algorithm appears to// outperform, at least on judge.yosupo.jp :)while d == 1 {x = y;for _ in 0..r {y = f(y);d = gcd((x - y).abs(), n);if d != 1 { break; }}r *= 2;}if d == n {*c += 1;continue;}return d;}}/// Outputs (p, e) in p's ascending order.pub fn factorize(x: i64) -> Vec<(i64, usize)> {if x <= 1 { return vec![]; }let mut hm = std::collections::HashMap::new();let mut pool = vec![x];let mut c = 1;while let Some(u) = pool.pop() {if is_prime(u) {*hm.entry(u).or_insert(0) += 1;continue;}let p = pollard_rho(u, &mut c);pool.push(p);pool.push(u / p);}let mut v: Vec<_> = hm.into_iter().collect();v.sort();v}} // mod pollard_rhotrait Change { fn chmax(&mut self, x: Self); fn chmin(&mut self, x: Self); }impl<T: PartialOrd> Change for T {fn chmax(&mut self, x: T) { if *self < x { *self = x; } }fn chmin(&mut self, x: T) { if *self > x { *self = x; } }}fn dfs(pe: &[(i64, usize)], idx: usize, c: i64, rem: i64, phi: i64) -> MInt {if idx >= pe.len() {return MInt::new(c).pow(2 * rem) * phi;}let mut tot = dfs(pe, idx + 1, c, rem, phi);let (p, e) = pe[idx];let mut phi = phi * (p - 1);let mut rem = rem / p;for _ in 1..e + 1 {tot += dfs(pe, idx + 1, c, rem, phi);rem /= p;phi *= p;}tot}fn main() {// In order to avoid potential stack overflow, spawn a new thread.let stack_size = 104_857_600; // 100 MBlet thd = std::thread::Builder::new().stack_size(stack_size);thd.spawn(|| solve()).unwrap().join().unwrap();}fn solve() {input! {t: usize,nc: [(i64, i64); t],}for (n, c) in nc {let pe = pollard_rho::factorize(n);let mut tot = MInt::new(c).pow(n) * n;tot += dfs(&pe, 0, c, n, 1);tot *= MInt::new(2 * n).inv();println!("{}", tot);}}