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 C++ (GCC 9.2.1) (judge verdict: Accepted)

#include <iostream>
#include <vector>
#include <string>
using namespace std;

using cat = long long;

cat pow(cat a, cat e, cat mod) {
	if(e <= 0) return 1;
	cat x = pow(a, e/2, mod);
	x = x * x % mod;
	return (e&1) ? x * a % mod : x;
}

int main() {
	cin.sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int A, B, C, D;
	cin >> A >> B >> C >> D;
	cat mod = 998244353;
	vector< vector<cat> > pw(3001, vector<cat>(3001, 1));
	for(int i = 1; i <= 3000; i++) for(int j = 1; j <= 3000; j++) pw[i][j] = pw[i][j-1] * i % mod;
	vector< vector<cat> > pw_inv(3001, vector<cat>(3001, 1));
	for(int i = 1; i <= 3000; i++) {
		int r = pow(i, mod-2, mod);
		for(int j = 1; j <= 3000; j++) pw_inv[i][j] = pw_inv[i][j-1] * r % mod;
	}
	vector< vector<cat> > cnt(C+1, vector<cat>(D+1, 0));
	vector< vector<cat> > sx(C+1, vector<cat>(D+1, 0));
	vector< vector<cat> > sy(C+1, vector<cat>(D+1, 0));
	cnt[A][B] = 1;
	for(int i = A; i <= C; i++) for(int j = B; j <= D; j++) {
		if(i == A && j == B) continue;
		if(i == A) {
			cnt[i][j] = cnt[i][j-1] * i % mod;
			continue;
		}
		if(j == B) {
			cnt[i][j] = cnt[i-1][j] * j % mod;
			continue;
		}
		cnt[i][j] = ((i-1) * (j-1) + i-1 + j-1) % mod * cnt[i-1][j-1] % mod;
		if(i > 1) sx[i][j] = sx[i-1][j] + (i-2) * cnt[i-2][j-1] % mod * pw_inv[j][i-1] % mod;
		if(j > 1) sy[i][j] = sy[i][j-1] + (j-2) * cnt[i-1][j-2] % mod * pw_inv[i][j-1] % mod;
		cnt[i][j] = (cnt[i][j] + sx[i][j] % mod * pw[j][i] + sy[i][j] % mod * pw[i][j]) % mod;
	}
	cout << cnt[C][D] << "\n";
}