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# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProblemB
{
    class Program
    {
        static void Main(string[] args)
        {
            var abcd = Console.ReadLine().Split(' ').Select(x => long.Parse(x)).ToArray();
            var a = abcd[0];
            var b = abcd[1];
            var c = abcd[2];
            var d = abcd[3];
            long div = 998244353;
            var cMinusA = c - a;
            var dMinusB = d - b;
            var dp = new long[cMinusA + 1, dMinusB + 1];
            dp[0, 0] = 1;

            for (int i = 0; i <= cMinusA; i++)
            {
                for (int j = 0; j <= dMinusB; j++)
                {
                    if (i == 0 & j == 0)
                        continue;
                    if (i != 0 && j != 0)
                    {
                        dp[i, j] = (dp[i, j - 1] * (a + i)) % div;
                        dp[i, j] += (dp[i - 1, j] * (b + j)) % div;
                        dp[i, j] %= div;
                        dp[i, j] -= -div + (dp[i - 1, j - 1] * (a + i - 1) * (b + j - 1)) % div;
                        dp[i, j] %= div;
                    }
                    else if (i != 0)
                        dp[i, j] = (dp[i - 1, j] * b) % div;
                    else if (j != 0)
                        dp[i, j] = (dp[i, j - 1] * a) % div;
                }
            }
            Console.WriteLine(dp[cMinusA, dMinusB]);
        }

        static long modinv(long a,long m)
        {
            long b = m, u = 1, v = 0;
            while (b != 0)
            {
                long t = a / b;
                a -= t * b;
                var temp = a;
                a = b;
                b = temp;
                u -= t * v;
                temp = u;
                u = v;
                v = temp;
            }
            u %= m;
            if (u < 0) u += m;
            return u;
        }
//long firstCase = 1;
//var cMinusA = c - a;
//var dMinusB = d - b;
//long res = 0;
//            for (int i = 0; i<cMinusA; i++)
//            {
//                firstCase = (firstCase* b) % div;
//            }
//            for (int i = 0; i<dMinusB; i++)
//            {
//                firstCase = (firstCase* c) % div;
//            }
//            res += firstCase;

//            for (int i = 0; i<cMinusA; i++)
//            {
//                firstCase = (firstCase* modinv(b, div)) % div;
//                var temp = firstCase;
//var caseNum = c - i - 1;
//                for (int j = 0; j<dMinusB; j++)
//                {
//                    temp = ((temp* modinv(c, div)) % div* caseNum) % div;
//                    res = (res + temp) % div;
             

    }
}