結果

問題 No.886 Direct
ユーザー akakimidori
提出日時 2021-11-29 20:03:48
言語 Rust
(1.83.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
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 32
権限があれば一括ダウンロードができます
コンパイルメッセージ
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

ソースコード

diff #
プレゼンテーションモードにする

// ---------- 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();
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0