結果
問題 | No.886 Direct |
ユーザー | akakimidori |
提出日時 | 2021-11-29 20:03:48 |
言語 | Rust (1.77.0 + proconio) |
結果 |
AC
|
実行時間 | 98 ms / 4,000 ms |
コード長 | 6,155 bytes |
コンパイル時間 | 24,285 ms |
コンパイル使用メモリ | 381,572 KB |
実行使用メモリ | 6,944 KB |
最終ジャッジ日時 | 2024-07-02 13:22:42 |
合計ジャッジ時間 | 16,651 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 1 ms
6,812 KB |
testcase_01 | AC | 1 ms
6,816 KB |
testcase_02 | AC | 1 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,940 KB |
testcase_04 | AC | 1 ms
6,940 KB |
testcase_05 | AC | 1 ms
6,940 KB |
testcase_06 | AC | 1 ms
6,944 KB |
testcase_07 | AC | 1 ms
6,940 KB |
testcase_08 | AC | 1 ms
6,940 KB |
testcase_09 | AC | 1 ms
6,944 KB |
testcase_10 | AC | 1 ms
6,940 KB |
testcase_11 | AC | 1 ms
6,944 KB |
testcase_12 | AC | 1 ms
6,944 KB |
testcase_13 | AC | 1 ms
6,944 KB |
testcase_14 | AC | 1 ms
6,940 KB |
testcase_15 | AC | 1 ms
6,944 KB |
testcase_16 | AC | 1 ms
6,940 KB |
testcase_17 | AC | 2 ms
6,944 KB |
testcase_18 | AC | 3 ms
6,940 KB |
testcase_19 | AC | 3 ms
6,944 KB |
testcase_20 | AC | 2 ms
6,944 KB |
testcase_21 | AC | 2 ms
6,944 KB |
testcase_22 | AC | 3 ms
6,940 KB |
testcase_23 | AC | 51 ms
6,940 KB |
testcase_24 | AC | 64 ms
6,940 KB |
testcase_25 | AC | 41 ms
6,940 KB |
testcase_26 | AC | 46 ms
6,944 KB |
testcase_27 | AC | 98 ms
6,944 KB |
testcase_28 | AC | 98 ms
6,944 KB |
testcase_29 | AC | 1 ms
6,944 KB |
testcase_30 | AC | 1 ms
6,944 KB |
testcase_31 | AC | 80 ms
6,944 KB |
testcase_32 | AC | 81 ms
6,940 KB |
testcase_33 | AC | 80 ms
6,940 KB |
testcase_34 | AC | 82 ms
6,940 KB |
testcase_35 | AC | 81 ms
6,940 KB |
コンパイルメッセージ
warning: function `gcd` is never used --> src/main.rs:220:4 | 220 | fn gcd(a: usize, b: usize) -> usize { | ^^^ | = note: `#[warn(dead_code)]` on by default
ソースコード
// ---------- begin recurse ---------- // reference // https://twitter.com/noshi91/status/1393952665566994434 // https://twitter.com/shino16_cp/status/1393933468082397190 pub fn recurse<A, R, F>(f: F) -> impl Fn(A) -> R where F: Fn(&dyn Fn(A) -> R, A) -> R, { fn call<A, R, F>(f: &F, a: A) -> R where F: Fn(&dyn Fn(A) -> R, A) -> R, { f(&|a| call(f, a), a) } move |a| call(&f, a) } // ---------- end recurse ---------- use std::marker::*; use std::ops::*; pub trait Modulo { fn modulo() -> u32; } pub struct ConstantModulo<const M: u32>; impl<const M: u32> Modulo for ConstantModulo<{ M }> { fn modulo() -> u32 { M } } pub struct ModInt<T>(u32, PhantomData<T>); impl<T> Clone for ModInt<T> { fn clone(&self) -> Self { Self::new_unchecked(self.0) } } impl<T> Copy for ModInt<T> {} impl<T: Modulo> Add for ModInt<T> { type Output = ModInt<T>; fn add(self, rhs: Self) -> Self::Output { let mut v = self.0 + rhs.0; if v >= T::modulo() { v -= T::modulo(); } Self::new_unchecked(v) } } impl<T: Modulo> AddAssign for ModInt<T> { fn add_assign(&mut self, rhs: Self) { *self = *self + rhs; } } impl<T: Modulo> Sub for ModInt<T> { type Output = ModInt<T>; fn sub(self, rhs: Self) -> Self::Output { let mut v = self.0 - rhs.0; if self.0 < rhs.0 { v += T::modulo(); } Self::new_unchecked(v) } } impl<T: Modulo> SubAssign for ModInt<T> { fn sub_assign(&mut self, rhs: Self) { *self = *self - rhs; } } impl<T: Modulo> Mul for ModInt<T> { type Output = ModInt<T>; fn mul(self, rhs: Self) -> Self::Output { let v = self.0 as u64 * rhs.0 as u64 % T::modulo() as u64; Self::new_unchecked(v as u32) } } impl<T: Modulo> MulAssign for ModInt<T> { fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs; } } impl<T: Modulo> Neg for ModInt<T> { type Output = ModInt<T>; fn neg(self) -> Self::Output { if self.is_zero() { Self::zero() } else { Self::new_unchecked(T::modulo() - self.0) } } } impl<T> std::fmt::Display for ModInt<T> { fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl<T> std::fmt::Debug for ModInt<T> { fn fmt<'a>(&self, f: &mut std::fmt::Formatter<'a>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl<T: Modulo> std::str::FromStr for ModInt<T> { type Err = std::num::ParseIntError; fn from_str(s: &str) -> Result<Self, Self::Err> { let val = s.parse::<u32>()?; Ok(ModInt::new(val)) } } impl<T: Modulo> From<usize> for ModInt<T> { fn from(val: usize) -> ModInt<T> { ModInt::new_unchecked((val % T::modulo() as usize) as u32) } } impl<T: Modulo> From<u64> for ModInt<T> { fn from(val: u64) -> ModInt<T> { ModInt::new_unchecked((val % T::modulo() as u64) as u32) } } impl<T: Modulo> From<i64> for ModInt<T> { fn from(val: i64) -> ModInt<T> { if val >= 0 { ModInt::from(val as u64) } else { -ModInt::from((-val) as u64) } } } impl<T> ModInt<T> { pub fn new_unchecked(n: u32) -> Self { ModInt(n, PhantomData) } pub fn zero() -> Self { ModInt::new_unchecked(0) } pub fn one() -> Self { ModInt::new_unchecked(1) } pub fn is_zero(&self) -> bool { self.0 == 0 } } impl<T: Modulo> ModInt<T> { pub fn new(d: u32) -> Self { ModInt::new_unchecked(d % T::modulo()) } pub fn pow(&self, mut n: u64) -> Self { let mut t = Self::one(); let mut s = *self; while n > 0 { if n & 1 == 1 { t *= s; } s *= s; n >>= 1; } t } pub fn inv(&self) -> Self { assert!(!self.is_zero()); self.pow(T::modulo() as u64 - 2) } } type M = ModInt<ConstantModulo<1_000_000_007>>; fn read() -> (usize, usize) { let mut s = String::new(); std::io::stdin().read_line(&mut s).unwrap(); let a = s .trim() .split_whitespace() .flat_map(|s| s.parse::<usize>()) .collect::<Vec<_>>(); (a[0], a[1]) } fn calc<F, G>(h: usize, w: usize, f: F, g: G) -> M where F: Fn(usize, usize) -> M, G: Fn(usize, usize) -> M, { assert!(h <= w); use std::cell::*; let memo = RefCell::new(std::collections::HashMap::<(usize, usize), M>::new()); let res = recurse(|rec, (h, w): (usize, usize)| -> M { if let Some(v) = memo.borrow().get(&(h, w)) { return *v; } let mut ans = f(h, w); let mut l = 2; while l <= h { let r = std::cmp::min(h / (h / l), w / (w / l)); ans -= g(l, r) * rec((h / l, w / l)); l = r + 1; } memo.borrow_mut().insert((h, w), ans); ans })((h, w)); res } fn gcd(a: usize, b: usize) -> usize { if b == 0 { a } else { gcd(b, a % b) } } // 1 <= dx < H, 1 <= dy < W, gcd(dx, dy) == 1 // となるようなdx, dy について // (H - dx)(W - dy) の和 // fn run() { let (h, w) = read(); let mut ans = M::from(h * (w - 1) + w * (h - 1)); if h > 1 && w > 1 { let (h, w) = (h.min(w), h.max(w)); let inv6 = M::new(6).inv(); let two = |n: usize| -> M { M::from(n * (n + 1)) * M::from(2 * n + 1) * inv6 }; let one = |n: usize| -> M { M::from(n * (n + 1) / 2) }; let mut add = M::zero(); add += M::from(h * w) * calc(h - 1, w - 1, |h, w| M::from(h * w), |l, r| M::from(r - l + 1)); add -= M::from(w) * calc(h - 1, w - 1, |h, w| M::from(w) * one(h), |l, r| one(r) - one(l - 1)); add -= M::from(h) * calc(h - 1, w - 1, |h, w| M::from(h) * one(w), |l, r| one(r) - one(l - 1)); add += calc(h - 1, w - 1, |h, w| one(h) * one(w), |l, r| two(r) - two(l - 1)); ans += add + add; } println!("{}", ans); } fn main() { run(); }