AtCoder Beginner Contest 354 D

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));
}