Problem:
Score : 600 points

Problem Statement

We have a grid with A horizontal rows and B vertical columns, with the squares painted white. On this grid, we will repeatedly apply the following operation:

Assume that the grid currently has a horizontal rows and b vertical columns. Choose "vertical" or "horizontal".

If we choose "vertical", insert one row at the top of the grid, resulting in an (a+1) \times b grid.

If we choose "horizontal", insert one column at the right end of the grid, resulting in an a \times (b+1) grid.

Then, paint one of the added squares black, and the other squares white.

Assume the grid eventually has C horizontal rows and D vertical columns. Find the number of ways in which the squares can be painted in the end, modulo 998244353.

Constraints

1 \leq A \leq C \leq 3000

1 \leq B \leq D \leq 3000

A, B, C, and D are integers.

Input

Input is given from Standard Input in the following format:

A B C D

Output

Print the number of ways in which the squares can be painted in the end, modulo 998244353.

Sample Input 1

1 1 2 2

Sample Output 1

3

Any two of the three squares other than the bottom-left square can be painted black.

Sample Input 2

2 1 3 4

Sample Output 2

65

Sample Input 3

31 41 59 265

Sample Output 3

387222020

Solution in Rust (1.42.0) (judge verdict: Accepted)

#![allow(unused_imports)]
use std::io;
use std::cmp;
use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::collections::HashSet;
use std::f64::consts::PI;
use std::str::FromStr;
use std::cmp::Reverse;

#[allow(dead_code)]
type Error = Box<dyn std::error::Error>;

fn read_line() -> String {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).ok();
    buf
}

struct Scanner {
    buff: Vec<String>,
    pos: usize,
}

#[allow(dead_code)]
impl Scanner {
    pub fn new() -> Self {
        Scanner {
            buff: Vec::new(),
            pos: 0,
        }
    }

    pub fn next<T: FromStr>(&mut self) -> T {
        while self.buff.len() <= self.pos {
            self.pos = 0;
            self.buff = read_line().split_whitespace().map(|s| s.to_owned()).collect();
        }

        let result = self.buff[self.pos].parse::<T>();
        self.pos += 1;
        result.ok().unwrap()
    }

    pub fn next_line(&mut self) -> String {
        let result  = read_line().trim().to_owned();
        self.buff.clear();
        self.pos = 0;

        result
    }

    pub fn next_vec<T: FromStr>(&mut self) -> Vec<T> {
        self.buff.clear();
        self.pos = 0;
        read_line().trim().split_whitespace().map(|s| s.parse().ok().unwrap()).collect()
    }
    
    pub fn next_line_chars(&mut self) -> Vec<char> {
        let result  = read_line().trim().chars().collect();
        self.buff.clear();
        self.pos = 0;

        result
    }
}

const MOD: u64 = 998_244_353;

fn main() {
    let mut sc = Scanner::new();

    let a: usize = sc.next();
    let b: usize = sc.next();
    let c: usize = sc.next();
    let d: usize = sc.next();

    let mut memo = vec![vec![0u64; d+10]; c+10];
    memo[a][b] = 1;
    memo[a+1][b] = b as u64;
    memo[a][b+1] = a as u64;

    for i in a..c {
        memo[i+1][b] = (memo[i][b] * b as u64) % MOD;
    }
    for i in b..d {
        memo[a][i+1] = (memo[a][i] * a as u64) % MOD;
    }

    for i in a..c {
        for j in b..d {
            let x = i as u64;
            let y = j as u64;
            memo[i+1][j+1] += memo[i+1][j] * (x+1);
            memo[i+1][j+1] %= MOD;
            memo[i+1][j+1] += memo[i][j+1] * (y+1);
            memo[i+1][j+1] %= MOD;
            memo[i+1][j+1] += MOD - memo[i][j] * x * y % MOD;
            memo[i+1][j+1] %= MOD;
        }
    }

    println!("{}", memo[c][d]);
}