https://atcoder.jp/contests/abc354/tasks/abc354_d
幅が4の倍数で高さが2の倍数の部分とそれ以外の3つの部分に分けて足し合わせます。
// AtCoder Wallpaper #![allow(non_snake_case)] //////////////////// library //////////////////// fn read<T: std::str::FromStr>() -> T { let mut line = String::new(); std::io::stdin().read_line(&mut line).ok(); line.trim().parse().ok().unwrap() } fn read_vec<T: std::str::FromStr>() -> Vec<T> { read::<String>().split_whitespace() .map(|e| e.parse().ok().unwrap()).collect() } fn div(n: i64, d: i64) -> i64 { if n < 0 { (n - d + 1) / d } else { n / d } } fn modulo(n: i64, d: i64) -> i64 { let r = n % d; if r < 0 { r + d } else { r } } fn divmod(n: i64, d: i64) -> (i64, i64) { (div(n, d), modulo(n, d)) } //////////////////// process //////////////////// fn read_input() -> (i64, i64, i64, i64) { let v = read_vec(); let (A, B, C, D) = (v[0], v[1], v[2], v[3]); (A, B, C, D) } // y方向は偶数、x方向は任意 fn Fx(rx: i64, rdx: i64) -> i64 { let v: [i64; 4] = [3, 3, 1, 1]; let mut s = 0; for x in 0..rdx { s += v[((x+rx)&3) as usize] } s } // x方向は4の倍数、y方向は任意 fn Fy(rdy: i64) -> i64 { 4 * rdy } fn Fxy(rx: i64, ry: i64, rdx: i64, rdy: i64) -> i64 { let v: [[i64; 4]; 2] = [[2, 1, 0, 1], [1, 2, 1, 0]]; let mut s = 0; for y in 0..rdy { for x in 0..rdx { s += v[((y+ry)&1) as usize][((x+rx)&3) as usize] } } s } fn F(A: i64, B: i64, C: i64, D: i64) -> i64 { let dx = C - A; let dy = D - B; let (qx, rdx) = divmod(dx, 4); let (qy, rdy) = divmod(dy, 2); let rx = modulo(A, 4); let ry = modulo(B, 2); let mut S = qx * qy * 8; S += Fx(rx, rdx) * qy; S += Fy(rdy) * qx; S += Fxy(rx, ry, rdx, rdy); S } fn main() { let (A, B, C, D) = read_input(); println!("{}", F(A, B, C, D)); }