package main import ( "bufio" "fmt" "os" "sort" "strconv" ) func Assert(ok bool) { if !ok { panic("assertion failed") } } var sc = func() *bufio.Scanner { sc := bufio.NewScanner(os.Stdin) sc.Split(bufio.ScanWords) return sc }() func Str() string { sc.Scan() return sc.Text() } func Int() int { x, _ := strconv.Atoi(Str()) return x } func Float() float64 { x, _ := strconv.ParseFloat(Str(), 64) return x } var wr = bufio.NewWriter(os.Stdout) func Out(a ...interface{}) { fmt.Fprintln(wr, a...) } func Format(a []int) string { s := fmt.Sprint(a) return s[1 : len(s)-1] } func Chmin(a *int, b int) bool { if b < *a { *a = b return true } return false } func Chmax(a *int, b int) bool { if b > *a { *a = b return true } return false } func Max(a ...int) int { mx := a[0] for _, x := range a { if x > mx { mx = x } } return mx } func Min(a ...int) int { mn := a[0] for _, x := range a { if x < mn { mn = x } } return mn } func Sum(a ...int) int { s := 0 for _, x := range a { s += x } return s } // truncated func Divmod(a, b int) (int, int) { q := a / b r := a - q*b return q, r } func Lb(a []int, x int) int { n := len(a) f := func(i int) bool { return a[i] >= x } return sort.Search(n, f) } func Ub(a []int, x int) int { n := len(a) f := func(i int) bool { return a[i] > x } return sort.Search(n, f) } func main() { defer wr.Flush() t := 1 // t := Int() for ; t > 0; t-- { Solve() } } func Iota(n int) []int { a := make([]int, n) for i := 0; i < n; i++ { a[i] = i } return a } func Cumprod(m int, a []int) { n := len(a) for i := 0; i < n-1; i++ { a[i+1] *= a[i] a[i+1] %= m } } func Fact(m, n int) []int { f := Iota(n) f[0] = 1 Cumprod(m, f) return f } func InvTable(m, n int) []int { f := make([]int, n) f[1] = 1 for i := 2; i < n; i++ { q, r := Divmod(m, i) f[i] = m - q*f[r]%m } return f } func InvFact(m, n int) []int { f := InvTable(m, n) f[0] = 1 Cumprod(m, f) return f } func Egcd(a, b int) (int, int, int) { if b == 0 { if a < 0 { return -a, -1, 0 } else { return a, 1, 0 } } q, r := Divmod(a, b) g, s, t := Egcd(b, r) return g, t, s - q*t } func Inv(m, a int) int { Assert(0 < a && a < m) g, x, _ := Egcd(a, m) Assert(g == 1) if x < 0 { x += m } return x } type Tables struct { F, Fi, Inv []int m int } func ( t *Tables, ) Init(m, n int) *Tables { f := make([]int, n) f[0] = 1 for i := 1; i < n; i++ { f[i] = f[i-1] * i % m } fi := make([]int, n) inv := make([]int, n) fi[n-1] = Inv(m, f[n-1]) for i := n - 1; i > 0; i-- { fi[i-1] = fi[i] * i % m inv[i] = fi[i] * f[i-1] % m } *t = Tables{ F: f, Fi: fi, Inv: inv, m: m, } return t } func (t *Tables) P(n, k int) int { if k < 0 || n < k { return 0 } return t.F[n] * t.Fi[n-k] % t.m } func (t *Tables) C(n, k int) int { if k < 0 { return 0 } return t.P(n, k) * t.Fi[k] % t.m } func (t *Tables) H(n, k int) int { return t.C(n-1+k, k) } func (t *Tables) IP(n, k int) int { Assert(0 <= k && k <= n) return t.Fi[n] * t.F[n-k] % t.m } func (t *Tables) IC(n, k int) int { return t.IP(n, k) * t.F[k] % t.m } func Solve() { x, y := Int(), Int() z, w := Int(), Int() Chmax(&z, 1) Chmax(&w, 1) const m int = 998244353 t := new(Tables).Init(m, 1<<20) ans := t.F[x+y-z-w] ans *= t.C(x, z) ans %= m ans *= t.C(y, w) ans %= m Out(ans) }