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 Iota(n, v int) []int { a := make([]int, n) for i := 0; i < n; i++ { a[i] = v + i } return a } func YesNo( y, n string, ) func(bool) { return func(f bool) { if f { Out(y) } else { Out(n) } } } var Yes = YesNo("Yes", "No") // var Yes = YesNo("yes", "no") // var Yes = YesNo("YES", "NO") func main() { defer wr.Flush() t := 1 // t := Int() for ; t > 0; t-- { Solve() } } 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 } const mod = 998244353 type Comb struct { F, Fi, Inv []int } // new(Comb).Init() func (c *Comb) Init(n int) *Comb { f := make([]int, n) fi := make([]int, n) iv := make([]int, n) f[0] = 1 for i := 1; i < n; i++ { f[i] = f[i-1] * i % mod } fi[n-1] = Inv(mod,f[n-1]) for i := n - 1; i >= 1; i-- { fi[i-1] = fi[i] * i % mod iv[i] = fi[i] * f[i] % mod } c.F, c.Fi, c.Inv = f, fi, iv return c } func (c *Comb) P(n, k int) int { if k < 0 || n < k { return 0 } return c.F[n] * c.Fi[n-k] % mod } func (c *Comb) C(n, k int) int { if k < 0 || n < k { return 0 } return c.P(n, k) * c.Fi[k] % mod } func (c *Comb) H(n, k int) int { return c.C(n-1+k, k) } func (c *Comb) IP(n, k int) int { Assert(0 <= k && k <= n) return c.Fi[n] * c.F[n-k] % mod } func (c *Comb) IC(n, k int) int { return c.IP(n, k) * c.F[k] % mod } func Solve() { x := Int() y := Int() z := Int() w := Int() Chmax(&z, 1) Chmax(&w, 1) f := new(Comb).Init(1<<20) res := f.F[x+y-z-w] res *= f.C(x, z) res %= mod res *= f.C(y, w) res %= mod Out(res) }