Problem:
Score : 600 points

Problem Statement

Snuke is standing on a two-dimensional plane. In one operation, he can move by 1 in the positive x-direction, or move by 1 in the positive y-direction.

Let us define a function f(r, c) as follows:

f(r,c) := (The number of paths from the point (0, 0) to the point (r, c) that Snuke can trace by repeating the operation above)

Given are integers r_1, r_2, c_1, and c_2.
Find the sum of f(i, j) over all pair of integers (i, j) such that r_1 ≤ i ≤ r_2 and c_1 ≤ j ≤ c_2, and compute this value modulo (10^9+7).

Constraints

1 ≤ r_1 ≤ r_2 ≤ 10^6

1 ≤ c_1 ≤ c_2 ≤ 10^6

All values in input are integers.

Input

Input is given from Standard Input in the following format:

r_1 c_1 r_2 c_2

Output

Print the sum of f(i, j) modulo (10^9+7).

Sample Input 1

1 1 2 2

Sample Output 1

14

For example, there are two paths from the point (0, 0) to the point (1, 1): (0,0) → (0,1) → (1,1) and (0,0) → (1,0) → (1,1), so f(1,1)=2.

Similarly, f(1,2)=3, f(2,1)=3, and f(2,2)=6. Thus, the sum is 14.

Sample Input 2

314 159 2653 589

Sample Output 2

602215194

Solution in Rust (1.15.1) (judge verdict: Time Limit Exceeded)

use std::vec::Vec;

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.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 read_touple<T: std::str::FromStr + Copy>() -> (T, T, T, T) {
  let v: Vec<T> = read_vec();
  assert_eq!(v.len(), 4);
  (v[0], v[1], v[2], v[3])
}

const MOD: usize = 1_000_000_000 + 7;
fn main() {
    let (r1, c1, r2, c2) = read_touple::<usize>();
    let mdc: ModConb = ModConb::new(r2+c2+1);
    let mut ans: Mod = Mod::new_zero();
    for i in r1..r2+1 {
      for j in c1..c2+1 {
        //println!("i+j = {}, i = {}, c = {}", i+j, i,  mdc.get(i+j, i).unwrap());
        ans = ans + mdc.get(i+j, i);
      }
    }

    println!("{}", ans.unwrap());
}

use std::cmp::Ord;
use std::cmp::*;
use std::ops::Add;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Neg;
use std::ops::Sub;


#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
struct Mod {
  val: usize,
}

// 和を定義
impl Add for Mod {
  type Output = Mod;
  // O(1)
  fn add(self, other: Mod) -> Mod {
    Mod {
      val: (self.val + other.val) % MOD,
    }
  }
}

// 差を定義
impl Sub for Mod {
  type Output = Mod;

  // O(1)
  fn sub(self, other: Mod) -> Mod {
    let mx = max(self.val, other.val);
    let mn = min(self.val, other.val);

    Mod {
      val: (mx - mn) % MOD,
    }
  }
}

// 積を定義
impl Mul for Mod {
  type Output = Mod;

  // O(1)
  fn mul(self, other: Mod) -> Mod {
    Mod {
      val: (self.val * other.val) % MOD,
    }
  }
}

// 加法単位元
impl Neg for Mod {
  type Output = Mod;

  // O(1)
  fn neg(self) -> Mod {
    Mod {
      val: MOD - self.val,
    }
  }
}

// 逆元を定義
// フェルマーの小定理により実装
impl Div for Mod {
  type Output = Mod;

  //O(logN)
  fn div(self, other: Mod) -> Mod {
    self * other.inv()
  }
}

impl Mod {
  // コンストラクター
  fn new(n: usize) -> Mod {
    Mod { val: n % MOD }
  }

  // 加法単位元
  fn new_zero() -> Mod {
    Mod { val: 0 }
  }

  // 乗法単位元
  fn new_one() -> Mod {
    Mod { val: 1 }
  }

  // 加法逆元
  // 上記にて定義

  // 乗法逆元
  fn inv(self) -> Mod {
    if self.val == 0 {
      panic!("zero divide");
    }
    self.pow(MOD - 2)
  }

  // 累乗を定義
  // O(logN)
  fn pow(self, n: usize) -> Mod {
    let mut res = 1;
    let mut a = self.unwrap();
    let mut n = n;

    while n > 0 {
      if n % 2 == 0 {
        a = a * a;
        n /= 2;
      } else {
        res = res * a;
        a = a * a;
        n /= 2;
      }
      res %= MOD;
      a %= MOD;
    }
    Mod::new(res)
  }

  // 最大公約数
  // O(logN)
  fn gcd(self, other: Mod) -> usize {
    let mut x = self.val;
    let mut y = other.val;
    while y != 0 {
      let t = y;
      y = x % y;
      x = t;
    }
    x
  }

  // 階乗
  // O(N)
  fn fact(self) -> Mod {
    let mut res = 1;
    for i in 1..self.val + 1 {
      res *= i;
      res %= MOD;
    }

    Mod::new(res)
  }

  // 順列
  fn perm(self, other: Mod) -> Mod {
    let mut res = Mod::new_one();
    for x in (self.val - other.val + 1)..self.val + 1 {
      res = res * Mod::new(x);
    }

    res
  }

  // 組み合わせ O(N)
  fn conb(self, other: Mod) -> Mod {
    if self < other {
      return Mod::new_zero();
    }
    self.fact() / (other.fact() * (self - other).fact())
  }
  fn unwrap(self) -> usize {
    self.val % MOD
  }
}

#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
struct ModConb {
  table: Vec<usize>,
  table_inv: Vec<usize>,
  n: usize,
}

impl ModConb {
  // O(N)
  fn new(n: usize) -> ModConb {
    // 階乗のテーブル
    let mut table = vec![0; n + 1];
    // 逆元計算用テーブル
    let mut table_calc = vec![0; n + 1];
    // 逆元のテーブル
    let mut table_inv = vec![0; n + 1];

    // init
    table[0] = 1;
    table[1] = 1;
    table_calc[0] = 0;
    table_calc[1] = 1;
    table_inv[0] = 1;
    table_inv[1] = 1;

    for i in 2..n + 1 {
      table[i] = table[i - 1] * i % MOD;
      table_calc[i] = ((MOD - table_calc[MOD % i]) * (MOD / i)) % MOD;
      table_inv[i] = table_inv[i - 1] * table_calc[i] % MOD;
    }

    ModConb {
      table: table,
      table_inv: table_inv,
      n: n,
    }
  }
  // O(1)
  fn get(&self, i: usize, j: usize) -> Mod {
    if i < j {
      return Mod { val: 0 };
    }
    Mod {
      val: ((self.table[i] * self.table_inv[j]) % MOD) * self.table_inv[i - j] % MOD,
    }
  }
}