CodeEff/ECCO huggingface dataset:
# Original solution
n=int(eval(input()))
ans=10**13
for i in range(1,int(n**0.5)+1):
    j=n//i
    if n%i==0:
        ans=min(ans,i+j)
print((ans-2))


# Optimized solution
n=int(eval(input()))
ans=10**18
for i in range(1,int(n**0.5)+1):
    if n%i!=0:continue
    j=n//i
    t=i+j-2
    ans=min(t,ans)
print(ans)
# Original solution
import math
n = int(eval(input()))

a,b = 1,n
for i in range(1,int(math.sqrt(n)+1)):
    if n%i == 0:
        q = n//i
        if abs(a-b) > abs(q-i):
            a,b = i,q

print(((a-1) + (b-1)))       

# Optimized solution
import math
n = int(eval(input()))

ans = float("inf")
for i in range(1,int(math.sqrt(n)+1)):
    if n%i == 0:
        if (i-1)+(n//i-1) < ans:
            ans = (i-1)+(n//i-1)

print(ans)
# Original solution
# -*- coding: utf-8 -*-
n = int(eval(input()))

tmp = 10 ** 24
tmp2 = 1
tmp3 = 1
for i in range(1, 10 ** 6 + 1):
    if n % i == 0 and i + (n / i) < tmp:
        tmp = i + (n // i)
        tmp2 = i
        tmp3 = n // i
print((tmp2 + tmp3 - 2))


# Optimized solution
# -*- coding: utf-8 -*-
n = int(eval(input()))

tmp = pow(10, 13)
for i in range(1, int(pow(n, 0.5)) + 1):
    if n % i == 0 and abs(n // i - i) < tmp:
        tmp = abs(n // i - i)
        ans1 = n // i
        ans2 = i
#print(tmp, ans1, ans2)
print((ans1 + ans2 - 2))
# Original solution
# -*- coding: utf-8 -*-
n = int(eval(input()))

ans = pow(10, 30)
for i in range(1, int(pow(n, 0.5)) + 1):
    if n / i == n // i:
        j = n // i
        if i + j - 2 < ans:
            ans = i + j - 2
print(ans)


# Optimized solution
# -*- coding: utf-8 -*-
n = int(eval(input()))

ans = [10 ** 14, 10 ** 14]
for i in range(1, int(pow(n, 0.5)) + 1):
    if n % i == 0:
        tmp = n // i
        if tmp + i < sum(ans):
            ans = [i, tmp]
print((sum(ans) - 2))
# Original solution
N = int(eval(input()))
ans = float('inf')
for i in range(1,int(N**0.5) + 1):
    tmp = N / i
    if tmp.is_integer():
        if tmp == N:
            tmp_ans = N - 1
        else:
            tmp_ans = int(tmp) + i - 2
        if ans > tmp_ans:
            ans = tmp_ans
print(ans)

# Optimized solution
def make_divisors(n):
    divisors = []
    for i in range(1, int(n**0.5)+1):
        if n % i == 0:
            divisors.append(i)
            if i != n // i:
                divisors.append(n//i)

    divisors.sort()
    return divisors

10
N = int(eval(input()))
divisors = make_divisors(N)
ans = float('inf')
div_len = len(divisors)
if div_len % 2 == 0:
    i = div_len // 2
    j = div_len // 2 - 1
    ans = divisors[i] + divisors[j] - 2
else:
    ans = divisors[div_len // 2] * 2 - 2
print(ans)
# Original solution
from sys import stdin
import math

n = int(stdin.readline().rstrip())


def make_divisors(n):
    divisors = []
    for i in range(1, int(n**0.5)+1):
        if n % i == 0:
            divisors.append(i)
            if i != n // i:
                divisors.append(n//i)

    # divisors.sort()
    return divisors

li = make_divisors(n)

total = n+1

for i in range(len(li)):
    a = li[i]
    b = n//a
    total = min(total,a+b)

print((total-2))


# Optimized solution
n = int(eval(input()))

def make_divisors(n):
    divisors = []
    for i in range(1, int(n**0.5)+1):
        if n % i == 0:
            divisors.append(i)
            if i != n // i:
                divisors.append(n//i)
    divisors.sort()
    return divisors

mi = 10**15
for i in make_divisors(n):
    a = i;b = n//i
    mi = min(mi,a+b-2)

print(mi)
# Original solution


def make_divisors(n):
    divisors = []
    for i in range(1, int(n**0.5)+1):
        if n % i == 0:
            divisors.append(i)
            if i != n // i:
                divisors.append(n//i)

    # divisors.sort()
    return divisors


N = int(eval(input()))
a = make_divisors(N)
b = []
c = []

for j in range(len(a)):
    for k in range(len(a)):
        if a[j] * a[k] == N:
            b.append([a[j],a[k]])

for l in range(len(b)):
    c.append(b[l][0] + b[l][1])

print((min(c) - 2))


# Optimized solution
def make_divisors(n):
    divisors = []
    for i in range(1, int(n**0.5)+1):
        if n % i == 0:
            divisors.append(i)
            if i != n // i:
                divisors.append(n//i)

    return divisors

N = int(eval(input()))
a = make_divisors(N)
b = []
c = []

for j in range(len(a)):
    for k in range(len(a)):
        if a[j] * a[k] == N:
            b.append([a[j],a[k]])

for l in range(len(b)):
    c.append(b[l][0] + b[l][1])

print((min(c) - 2))
# Original solution
import itertools
from functools import reduce

N = int(eval(input()))

def prime_f(n):
    a = []
    while n % 2 == 0:
        a.append(2)
        n //= 2
    f = 3
    while f * f <= n:
        if n % f == 0:
            a.append(f)
            n //= f
        else:
            f += 2
    if n != 1:
        a.append(n)
    return a
    
A = prime_f(N)

F = []
L = []

distance = []

C = []

if len(A) == 1:
  print((N - 1))
else:
  for i in range(1,len(A)):
    C = list(itertools.combinations(A,i))
    for j in range(0,len(C)):
      totalC = reduce(lambda x,y:x*y,C[j])
      div = int(N / totalC)
      distance.append(div + totalC)

  print((min(distance) - 2))

# Optimized solution
import itertools
from functools import reduce

N = int(eval(input()))
distance = []
C = []

def prime_f(n):
    a = []
    while n % 2 == 0:
        a.append(2)
        n //= 2
    f = 3
    while f * f <= n:
        if n % f == 0:
            a.append(f)
            n //= f
        else:
            f += 2
    if n != 1:
        a.append(n)
    return a  
A = prime_f(N)

if len(A) == 1:
  print((N - 1))
else:
  for i in range(1,len(A)):
    C = list(set(itertools.combinations(A,i)))
    for j in range(0,len(C)):
      totalC = reduce(lambda x,y:x*y,C[j])
      div = int(N / totalC)
      distance.append(div + totalC)

  print((min(distance) - 2))
# Original solution
n = int(eval(input()))
ans = n-1
cnt = 2
while cnt <= int(n**0.5)+1:
    if n%cnt==0:
        ans = min(ans, (cnt-1)+(n//cnt-1))
    cnt += 1
print(ans)

# Optimized solution
n = int(eval(input()))
print((min(a+(n//a)-2 for a in range(1, int(n**0.5)+1) if n%a==0)))
# Original solution
N = int(eval(input()))

ans = 10 ** 18
for i in range(1, int(N ** 0.5) + 1):
    if N % i == 0:
        j = N // i
        ans = min(ans, i + j - 2)

print(ans)


# Optimized solution
N = int(eval(input()))

ans = 10 ** 18

for i in range(1, int(N ** 0.5 + 0.5) + 1):
    if N % i == 0:
        walk = i + N // i - 2
        ans = min(ans, walk)

print(ans)
# Original solution
import math
N = int(eval(input()))
 
lim = int(math.sqrt(N))
 
x = 1
while True:
    if N % lim == 0:
        x = lim
        break
    lim = lim - 1
 
y = N // lim
 
print(((x - 1) + (y - 1)))

# Optimized solution
import math
N = int(eval(input()))
max = 0
max2 = 0
for i in range(2, int(math.sqrt(N)+ 2)):
    if N % i == 0:
        max = i
        max2 = N // i
if max != 0:
    print((max + max2 - 2))
else:
    print((N -1))
#print(max, max2)
# Original solution
L = int(eval(input()))
a=[int(eval(input())) for i in range(L)]
if L == 1:
    print((0))
    exit()
    
rightsum = [0]*(L+1)
leftsum = [0]*(L+1)
for i in range(1,L+1):
    rightsum[i] = rightsum[i-1]+a[i-1]
    leftsum[L-i] = leftsum[L+1-i]+a[L-i]
leftsum=leftsum[::-1]

Reright = [0]
Goright = [0]
for i in range(L):
    res = Reright[-1] 
    if a[i] == 0:
        Reright.append(min(rightsum[i+1],2+Reright[-1]))
        Goright.append(min(rightsum[i+1],1+min(Goright[-1],res)))
    else:
        Reright.append(min(rightsum[i+1],a[i]%2+Reright[-1]))
        Goright.append(min(rightsum[i+1],(a[i]+1)%2+min(Goright[-1],res)))
Releft = [0]
Goleft = [0]

for i in range(L):
    res = Releft[-1]
    if a[L-1-i]==0:
        Releft.append(min(leftsum[i+1],2+Releft[-1]))
        Goleft.append(min(leftsum[i+1],1+min(Goleft[-1],res)))
    else:
        Releft.append(min(leftsum[i+1],a[L-1-i]%2+Releft[-1]))
        Goleft.append(min(leftsum[i+1],(a[L-1-i]+1)%2+min(Goleft[-1],res)))



cand = []
for i in range(L+1):
    p1 = Reright[i]
    p2 = min(Reright[i],Goright[i])
    q1 = Releft[L-i]
    q2 = min(Releft[L-i],Goleft[L-i])
    cand.append(min(p1+q2,p2+q1))
    
print((min(cand)))
    

# Optimized solution
L = int(eval(input()))
a=[int(eval(input())) for i in range(L)]
if L == 1:
    print((0))
    exit()

#累積和
rightsum = [0]*(L+1)
leftsum = [0]*(L+1)
for i in range(1,L+1):
    rightsum[i] = rightsum[i-1]+a[i-1]
    leftsum[i] = leftsum[i-1]+a[L-i]

#Re:戻ってくる Go:戻ってこなくてもよい
Reright = [0]
Goright = [0]
for i in range(L):
    if a[i] == 0:
        Goright.append(min(rightsum[i+1],1+min(Goright[-1],Reright[-1])))
        Reright.append(min(rightsum[i+1],2+Reright[-1]))
    else:
        Goright.append(min(rightsum[i+1],(a[i]+1)%2+min(Goright[-1],Reright[-1])))
        Reright.append(min(rightsum[i+1],a[i]%2+Reright[-1]))
        
Releft = [0]
Goleft = [0]
for i in range(L):
    if a[L-1-i]==0:
        Releft.append(min(leftsum[i+1],2+Releft[-1]))
        Goleft.append(min(leftsum[i+1],1+min(Goleft[-1],Releft[-1])))
    else:
        Goleft.append(min(leftsum[i+1],(a[L-1-i]+1)%2+min(Goleft[-1],Releft[-1])))
        Releft.append(min(leftsum[i+1],a[L-1-i]%2+Releft[-1]))
        
#候補cand
cand = []
for i in range(L+1):
    p1 = Reright[i]
    p2 = min(Reright[i],Goright[i])
    q1 = Releft[L-i]
    q2 = min(Releft[L-i],Goleft[L-i])
    cand.append(min(p1+q2,p2+q1))
    
print((min(cand)))
# Original solution
L=int(eval(input()))
A=[int(eval(input())) for _ in range(L)]

INF=2*L

dp=[[INF for _ in range(5)] for _ in range(L+1)]

for j in range(5):
    dp[0][j]=0

for i in range(1,L+1):
    a=A[i-1]

    if A[i-1]==0:
        o=2
    else:
        o=A[i-1]%2

    e=(A[i-1]+1)%2


    dp[i][0]=dp[i-1][0]+a
    dp[i][1]=min(dp[i-1][0]+o,dp[i-1][1]+o)
    dp[i][2]=min(dp[i-1][0]+e,dp[i-1][1]+e,dp[i-1][2]+e)
    dp[i][3]=min(dp[i-1][0]+o,dp[i-1][1]+o,dp[i-1][2]+o,dp[i-1][3]+o)
    dp[i][4]=min(dp[i-1][0]+a,dp[i-1][1]+a,dp[i-1][2]+a,dp[i-1][3]+a,dp[i-1][4]+a)

print((min(dp[L])))

# Optimized solution
L=int(eval(input()))
A=[int(eval(input())) for _ in range(L)]
dp=[0 for _ in range(5)]

for i in range(1,L+1):
    a=A[i-1]
    back = a%2 if a>0 else 2
    through = (a+1)%2

    dp[4] = min(dp[0:5]) + a
    dp[3] = min(dp[0:4]) + back
    dp[2] = min(dp[0:3]) + through
    dp[1] = min(dp[0:2]) + back
    dp[0]=dp[0]+a

print((min(dp)))
# Original solution
L, *A = list(map(int, open(0)))

D = [(2, 1), (1, 0), (0, 1)]

s0 = s1 = s2 = s3 = s4 = 0

for a in A:
    e, o = D[(a - 1) % 2 + 1 if a else 0]

    s0 += a
    s1 = s0 if s0 < s1 + e else s1 + e
    s2 = s1 if s1 < s2 + o else s2 + o
    s3 = s2 if s2 < s3 + e else s3 + e
    s4 = s3 if s3 < s4 + a else s4 + a

print((min(s0, s1, s2, s3, s4)))


# Optimized solution
def main():
    L, *A = list(map(int, open(0)))

    D = [(2, 1), (1, 0), (0, 1)]

    s0 = s1 = s2 = s3 = s4 = 0

    for a in A:
        e, o = D[(a - 1) % 2 + 1 if a else 0]

        s0 += a
        s1 = s0 if s0 < s1 + e else s1 + e
        s2 = s1 if s1 < s2 + o else s2 + o
        s3 = s2 if s2 < s3 + e else s3 + e
        s4 = s3 if s3 < s4 + a else s4 + a

    print((min(s0, s1, s2, s3, s4)))

if __name__ == '__main__':
    main()
# Original solution
# -*- coding: utf-8 -*-
l = int(eval(input()))
al = [int(eval(input())) for _ in range(l)]
INF = 10**15
dp = [[INF]*5 for _ in range(l+1)]  # 0,偶数,奇数,偶数,0の状態
dp[0][0] = 0

def cost(i, k):
    # i番目を状態kにした時に必要な回数
    if k==0 or k==4:
        return al[i]
    elif k==1 or k==3:
        if al[i]>0:
            return al[i]%2
        else:
            return 2
    else:
        if al[i]%2==0:
            return 1
        else:
            return 0

for i in range(l):
    for j in range(5):
        for k in range(j,5):
            dp[i+1][k] = min(
                dp[i+1][k],
                dp[i][j] + cost(i, k)
            )

print((min(dp[l])))


# Optimized solution
# -*- coding: utf-8 -*-
l = int(eval(input()))
al = [int(eval(input())) for _ in range(l)]
INF = 10**15
dp = [INF]*5  # 0,偶数,奇数,偶数,0の状態
dp[0] = 0

def cost(i, k):
    # i番目を状態kにした時に必要な回数
    if k==0 or k==4:
        return al[i]
    elif k==1 or k==3:
        if al[i]>0:
            return al[i]%2
        else:
            return 2
    else:
        if al[i]%2==0:
            return 1
        else:
            return 0

for i in range(l):
    dp2 = [min(dp[:j+1]) for j in range(5)]
    for j in range(5):
        dp[j] = dp2[j] + cost(i,j)

    # for j in range(5):
    #     for k in range(j,5):
    #         dp[i+1][k] = min(
    #             dp[i+1][k],
    #             dp[i][j] + cost(i, k)
    #         )

print((min(dp)))
# Original solution
#https://atcoder.jp/contests/yahoo-procon2019-qual/tasks/yahoo_procon2019_qual_d
#2019-02-10

#DP

L = int(eval(input()))
A = [int(eval(input())) for i in range(L)]

DP = [[float("inf") for i in range(5)] for j in range(L+1)]
for i in range(5):
    DP[0][i] = 0

def cost(s, i, A):
    if s == 0 or s == 4:
        return A[i]
    elif s == 1 or s == 3:
        if A[i] > 0:
            if A[i]%2 == 0:
                return 0
            else:
                return 1
        else:
            return 2
    else:
        if A[i]%2 == 1:
            return 0
        else:
            return 1

for i in range(L):
    DP[i+1][0] = DP[i][0] + cost(0, i, A)
    DP[i+1][1] = min(DP[i][:2]) + cost(1, i, A)
    DP[i+1][2] = min(DP[i][:3]) + cost(2, i, A)
    DP[i+1][3] = min(DP[i][:4]) + cost(3, i, A)
    DP[i+1][4] = min(DP[i][:5]) + cost(4, i, A)



print((min(DP[L])))

# Optimized solution
#https://atcoder.jp/contests/yahoo-procon2019-qual/tasks/yahoo_procon2019_qual_d
#2019-02-10

#DP

L = int(eval(input()))
A = [int(eval(input())) for i in range(L)]

DP = [[0 for i in range(5)] for j in range(L+1)]

def cost(s, i, A):
    if s == 0 or s == 4:
        return A[i]
    elif s == 1 or s == 3:
        if A[i] > 0:
            if A[i]%2 == 0:
                return 0
            else:
                return 1
        else:
            return 2
    else:
        if A[i]%2 == 1:
            return 0
        else:
            return 1

for i in range(L):
    DP[i+1][0] = DP[i][0] + cost(0, i, A)
    DP[i+1][1] = min(DP[i][:2]) + cost(1, i, A)
    DP[i+1][2] = min(DP[i][:3]) + cost(2, i, A)
    DP[i+1][3] = min(DP[i][:4]) + cost(3, i, A)
    DP[i+1][4] = min(DP[i][:5]) + cost(4, i, A)



print((min(DP[L])))
# Original solution
#https://atcoder.jp/contests/yahoo-procon2019-qual/tasks/yahoo_procon2019_qual_d
#2019-02-11

#DP

L = int(eval(input()))

DP = [0 for i in range(5)]

def cost(a):
    if a:
        return [a, a%2, (a+1)%2, a%2, a]
    else:
        return [0, 2, 1, 2, 0]

def list_add(in1, in2):
    return [a + b for a, b in zip(in1, in2)]

for i in range(L):
    n = [min(DP[:i+1]) for i in range(5)]
    a = int(eval(input()))
    cos = cost(a)
    DP = list_add(n, cos)



print((min(DP)))

# Optimized solution
#https://atcoder.jp/contests/yahoo-procon2019-qual/tasks/yahoo_procon2019_qual_d
#2019-02-11

#DP

L = int(eval(input()))

DP = [0 for i in range(5)]

def cost(a):
    if a:
        return [a, a%2, (a+1)%2, a%2, a]
    else:
        return [0, 2, 1, 2, 0]

def list_add(in1, in2):
    return [a + b for a, b in zip(in1, in2)]

for i in range(L):
    a = int(eval(input()))
    cos = cost(a)
    DP[4] = min(DP[:5]) + cos[4]
    DP[3] = min(DP[:4]) + cos[3]
    DP[2] = min(DP[:3]) + cos[2]
    DP[1] = min(DP[:2]) + cos[1]
    DP[0] = min(DP[:1]) + cos[0]



print((min(DP)))
# Original solution
l = int(eval(input()))
a = []
for i in range(l):
  a.append(int(eval(input())))
  
dp=[[0]*5 for i in range(l+1)]

for i in range(0,l):
  if a[i]==0:
    even=2
  else:
    even=a[i]%2
  
  dp[i+1][0]=dp[i][0]+a[i]
  dp[i+1][1]=min(dp[i][0],dp[i][1]) + even
  dp[i+1][2]=min(dp[i][0],dp[i][1],dp[i][2]) + (a[i]+1)%2
  dp[i+1][3]=min(dp[i][0],dp[i][1],dp[i][2],dp[i][3]) + even
  dp[i+1][4]=min(dp[i][0],dp[i][1],dp[i][2],dp[i][3],dp[i][4]) + a[i]
  
print((min(dp[l])))
  

# Optimized solution
n  = int(eval(input()))
a = [int(eval(input())) for i in range(n)]

# 0区間、偶数区間(2以上)、奇数区間、偶数区間(2以上)、0区間
dp = [[0] * (5) for i in range(n + 1)]
for i in range(n):
    dp[i + 1][0] = dp[i][0] + a[i]

    dp[i + 1][1] = min(dp[i][0:2]) + (a[i] % 2)
    if a[i] == 0:
        dp[i + 1][1] += 2
        
    dp[i + 1][2] = min(dp[i][0:3]) + (a[i] + 1) % 2
    
    dp[i + 1][3] = min(dp[i][0:4]) + (a[i] % 2)
    if a[i] == 0:
        dp[i + 1][3] += 2
        
    dp[i + 1][4] = min(dp[i][0:5]) + a[i]

print((min(dp[-1])))
# Original solution
import sys
input = sys.stdin.readline
n = int(eval(input()))
a = [int(eval(input())) for i in range(n)]
b = [0]*n
for i in range(n):
  if a[i]%2:
    b[i] = 1
  elif a[i]:
    b[i] = 2
a.append(0)
b.append(0)
n += 1
DP = [[[10**18 for i in range(3)] for j in range(3)] for k in range(n+1)]
for i in range(3):
  for j in range(3):
    DP[0][i][j] = 0
for i in range(1,n+1):
  for k in (0,2):
    DP[i][0][k] = min(DP[i][0][k],DP[i-1][0][k]+abs(a[i-1]))
  for l in (1,2):
    DP[i][0][2] = min(DP[i][0][2],DP[i-1][l][2]+abs(a[i-1]))
  DP[i][0][2] = min(DP[i][0][2],DP[i-1][2][1]+abs(a[i-1]))

  DP[i][1][2] = min(DP[i][1][2],DP[i-1][0][0]+abs(b[i-1]-1))
  DP[i][1][2] = min(DP[i][1][2],DP[i-1][1][2]+abs(b[i-1]-1))
  DP[i][1][2] = min(DP[i][1][2],DP[i-1][2][1]+abs(b[i-1]-1))

  for k in (1,2):
    DP[i][2][k] = min(DP[i][2][k],DP[i-1][2][k]+abs(b[i-1]-2))
  DP[i][2][2] = min(DP[i][2][2],DP[i-1][1][2]+abs(b[i-1]-2))
  DP[i][2][1] = min(DP[i][2][1],DP[i-1][0][0]+abs(b[i-1]-2))
print((min(*DP[n][0])))

# Optimized solution
import sys
input = sys.stdin.readline
n = int(eval(input()))
a = [int(eval(input())) for i in range(n)]
b = [0]*n
for i in range(n):
  if a[i]%2:
    b[i] = 1
  elif a[i]:
    b[i] = 2
DP = [[10**18 for i in range(5)] for j in range(n+1)]
for i in range(5):
    DP[0][i] = 0
for i in range(1,n+1):
  for j in range(5):
    for k in range(j,5):
      if k == 0 or k == 4:
        DP[i][k] = min(DP[i][k],DP[i-1][j]+a[i-1])
      elif k == 1 or k == 3:
        DP[i][k] = min(DP[i][k],DP[i-1][j]+abs(b[i-1]-2))
      else:
        DP[i][k] = min(DP[i][k],DP[i-1][j]+abs(b[i-1]-1))
print((min(DP[n])))
# Original solution
import sys

def main():
    input = sys.stdin.readline
    mod = 998244353
    
    a, b, c, d = list(map(int, input().split()))
    dp = dict()
    for i in range(a, c+1):
        for j in range(b, d+1):
            if i == a and j == b:
                dp[(i, j)] = 1
                continue
            if j == b:
                dp[(i, j)] = dp[(i-1, j)]*j%mod
                continue
            if i == a:
                dp[(i, j)] = dp[(i, j-1)]*i%mod
                continue
            dp[(i, j)] = (dp[(i-1, j)]*j+dp[(i, j-1)]*i+mod-dp[(i-1, j-1)]*(i-1)*(j-1))%mod
    print((dp[(c, d)]))        
    

if __name__ == "__main__":
    main()

# Optimized solution
import sys

def main():
    input = sys.stdin.readline
    mod = 998244353
    
    a, b, c, d = list(map(int, input().split()))
    dp = [[0]*(d+1) for _ in range(c+1)]
    for i in range(a, c+1):
        for j in range(b, d+1):
            if i == a and j == b:
                dp[i][j] = 1
                continue
            if j == b:
                dp[i][j] = dp[i-1][j]*j%mod
                continue
            if i == a:
                dp[i][j] = dp[i][j-1]*i%mod
                continue
            dp[i][j] = (dp[i-1][j]*j+dp[i][j-1]*i+mod-dp[i-1][j-1]*(i-1)*(j-1)%mod)%mod
    print((dp[c][d]))        
            

if __name__ == "__main__":
    main()
# Original solution
import bisect
import copy
import heapq
import sys
import itertools
import math
import queue
from functools import lru_cache
input = sys.stdin.readline
sys.setrecursionlimit(1000000)
mod = 998244353

def read_values(): return list(map(int, input().split()))
def read_index(): return [int(x) - 1 for x in input().split()]
def read_list(): return list(read_values())
def read_lists(N): return [read_list() for n in range(N)]


class Comb:
    def __init__(self, N):
        F = [1] * (N + 1)
        for i in range(N):
            F[i + 1] = (i + 1) * F[i] % mod

        self.d_inv = {}
        self.d_comb = {}
        self.F = F

    def inv(self, a):
        if a not in self.d_inv:
            self.d_inv[a] = pow(a, mod - 2, mod)
        return self.d_inv[a]

    def comb(self, a, b):
        if (a, b) not in self.d_comb:
            self.d_comb[(a, b)] = (self.F[a] * self.inv(self.F[a - b]) * self.inv(self.F[b])) % mod
            self.d_comb[(a, a - b)] = self.d_comb[(a, b)]
        return self.d_comb[(a, b)] 


def main():
    A, B, C, D = read_values()

    dp = [[0 for _ in range(D - B + 1)] for _ in range(C - A + 1)]
    dp[0][0] = 1

    for i in range(C - A):
        dp[i + 1][0] = dp[i][0] * B % mod
    for j in range(D - B):
        dp[0][j + 1] = dp[0][j] * A % mod

    for i in range(1, C - A + 1):
        for j in range(1, D - B + 1):
            dp[i][j] = dp[i - 1][j] * (B + j) + dp[i][j - 1] * (A + i) - dp[i - 1][j - 1] * (A + i - 1) * (B + j - 1) % mod

    print((dp[C - A][D - B] % mod))


if __name__ == "__main__":
    main()



# Optimized solution
import bisect
import copy
import heapq
import sys
import itertools
import math
import queue
from functools import lru_cache
input = sys.stdin.readline
sys.setrecursionlimit(1000000)
mod = 998244353

def read_values(): return list(map(int, input().split()))
def read_index(): return [int(x) - 1 for x in input().split()]
def read_list(): return list(read_values())
def read_lists(N): return [read_list() for n in range(N)]


def main():
    A, B, C, D = read_values()

    dp = [[0 for _ in range(D - B + 1)] for _ in range(C - A + 1)]
    dp[0][0] = 1

    for i in range(C - A):
        dp[i + 1][0] = dp[i][0] * B % mod
    for j in range(D - B):
        dp[0][j + 1] = dp[0][j] * A % mod

    for i in range(1, C - A + 1):
        for j in range(1, D - B + 1):
            dp[i][j] = (dp[i - 1][j] * (B + j)) % mod + (dp[i][j - 1] * (A + i)) % mod - (dp[i - 1][j - 1] * (A + i - 1) * (B + j - 1)) % mod
            dp[i][j] %= mod

    print((dp[C - A][D - B] % mod))


if __name__ == "__main__":
    main()