#include <bits/stdc++.h>
using namespace std;

#define rep(i,n) for(int i=0; i<(n); ++i)
#define rrep(i,n) for(int i=1; i<=(n); ++i)
#define drep(i,n) for(int i=(n)-1; i>=0; --i)
#define srep(i,s,t) for (int i = s; i < t; ++i)
#define foreach(it, v) for(typeof(v.begin()) it=v.begin(); it!=v.end(); ++it)
#define pb push_back
#define sz(x) (int)(x).size()
#define fi first
#define se second
#define v(T) vector<T>

typedef unsigned int uint;
typedef long long int ll;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef vector<pii> vpii;
typedef set<int> si;
template<typename T>string join(const v(T)&v)
{stringstream s;rep(i,sz(v))s<<' '<<v[i];return s.str().substr(1);}
template<typename T>inline ostream& operator<<(ostream&o,const v(T)&v)
{if(sz(v))o<<join(v);return o;}

//MOD//
const ll MOD = 998244353;
struct big;
big ex(big a, ll tms);
typedef struct big{
  ll val;
  big():val(0){}
  big(ll val):val((val%MOD+MOD)%MOD){}
  big& operator += (const big& obj){ (val+=obj.val)%=MOD; return *this;}
  big& operator -= (const big& obj){ (val+=MOD-obj.val)%=MOD; return *this;}
  big& operator *= (const big& obj){ (val*=obj.val)%=MOD; return *this;}
  big& operator /= (const big& obj){ (val*=ex(obj,MOD-2).val)%=MOD; return *this;}
  big operator + (const big& obj)const{ return big(*this) += obj;}
  big operator - (const big& obj)const{ return big(*this) -= obj;}
  big operator * (const big& obj)const{ return big(*this) *= obj;}
  big operator / (const big& obj)const{ return big(*this) /= obj;}
  bool operator < (const big& obj)const{ return val < obj.val;}
  bool operator == (const big& obj)const{ return val == obj.val;}
} big;
istream& operator >> (istream& i, big& obj){ i>>obj.val; return i;}
ostream& operator << (ostream& o, const big& obj){ o<<obj.val; return o;}
big ex(big obj, ll tms){
  if(!tms) return 1;
  big ret = ex(obj, tms/2);
  ret *= ret;
  return (tms&1) ? ret*obj : ret;
}
//MOD//

//COM//
const int COM_MAX = 2100000;
ll fac[COM_MAX], finv[COM_MAX], inv[COM_MAX];
void com_init() {
    fac[0] = fac[1] = 1; finv[0] = finv[1] = 1; inv[1] = 1;
    for (int i = 2; i < COM_MAX; i++){
        fac[i] = fac[i - 1] * i % MOD;
        inv[i] = MOD - inv[MOD%i] * (MOD / i) % MOD;
        finv[i] = finv[i - 1] * inv[i] % MOD;
    }
}
ll com(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}
//COM//

ll pow(ll n, int m){
  if(!m) return 1;
  ll ret = pow(n, m/2);
  ret *= ret;
  return (m&1) ? ret*n : ret;
}

template <class F, class T>
void convert(const F &f, T &t){
  stringstream ss;
  ss << f;
  ss >> t;
}

int  A,B,C,D;
big x[3010][3010][3]; // 1 -> multi on right 2 -> multi on top

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  com_init();

  cin >> A >> B >> C >> D;
  x[A][B][0] = 1;
  srep(i,A+1,C+1) {
    x[i][B][0] = x[i-1][B][0] * B;
  }
  srep(j,B+1,D+1) {
    x[A][j][0] = x[A][j-1][0] * A;
  }
  srep(i,A+1,C+1) {
    srep(j,B+1,D+1) {
      x[i][j][0] = (x[i][j-1][0] + x[i][j-1][1]) * (i-1);
      x[i][j][1] = (x[i-1][j][0] + x[i-1][j][2]) +
                    x[i-1][j][1] * j;
      x[i][j][2] = (x[i][j-1][0] + x[i][j-1][1]) +
                    x[i][j-1][2] * i;
    }
  }
  cout << (x[C][D][0] + x[C][D][1] + x[C][D][2]) << '\n' << endl;
  return 0;
}


Measured memory_bytes: 265216