CodeEff/ECCO huggingface dataset:
# Original solution
n,m=list(map(int,input().split()))
a=list(map(int,input().split()))
b=list(map(int,input().split()))
A=set(a);B=set(b)
if len(A)!=len(a) or len(B)!=len(b):
  print((0))
else:
  L=[]
  for i in range(n):
    l=[]
    for j in range(m):
      l.append(0)
    L.append(l)
  ct=1;ctn=0;ctm=0
  for k in range(m*n,0,-1):
    if k in A and k in B:
      L[n-ctn-1][m-ctm-1]=k
      ctn+=1;ctm+=1
    elif k in A:
      ct*=ctm;ctn+=1
    elif k in B:
      ct*=ctn;ctm+=1
    else:
      ct*=(ctm*ctn-m*n+k)
    if ct==0:
      break
    ct=ct%(10**9+7)
  print(ct)

# Optimized solution
n,m=list(map(int,input().split()))
a=list(map(int,input().split()))
b=list(map(int,input().split()))
A=set(a);B=set(b)
if len(A)!=len(a) or len(B)!=len(b):
  print((0))
else:
  L=[]
  l=[0 for j in range(m)]
  for i in range(n):
    L.append(l)
  ct=1;ctn=0;ctm=0
  for k in range(m*n,0,-1):
    if k in A and k in B:
      L[n-ctn-1][m-ctm-1]=k
      ctn+=1;ctm+=1
    elif k in A:
      ct*=ctm;ctn+=1
    elif k in B:
      ct*=ctn;ctm+=1
    else:
      ct*=(ctm*ctn-m*n+k)
    if ct==0:
      break
    ct=ct%(10**9+7)
  print(ct)
# Original solution
n,m=list(map(int,input().split()))
a=list(map(int,input().split()))
b=list(map(int,input().split()))
A=set(a);B=set(b)
if len(A)!=len(a) or len(B)!=len(b):
  print((0))
else:
  L=[[0 for j in range(m)] for i in range(n)]
  c=1;cn=0;cm=0
  for k in range(m*n,0,-1):
    if k in A and k in B:
      L[n-cn-1][m-cm-1]=k
      cn+=1;cm+=1
    elif k in A:
      c*=cm;cn+=1
    elif k in B:
      c*=cn;cm+=1
    else:
      c*=(cm*cn-m*n+k)
    if c==0:
      break
    c=c%(10**9+7)
  print(c)

# Optimized solution
n,m=list(map(int,input().split()))
a=list(map(int,input().split()))
b=list(map(int,input().split()))
A=set(a);B=set(b)
if len(A)!=len(a) or len(B)!=len(b):
  print((0))
else:
  c=1;cn=0;cm=0
  for k in range(m*n,0,-1):
    if k in A and k in B:
      cn+=1;cm+=1
    elif k in A:
      c*=cm;cn+=1
    elif k in B:
      c*=cn;cm+=1
    else:
      c*=(cm*cn-m*n+k)
    if c==0:
      break
    c=c%(10**9+7)
  print(c)
# Original solution
n,m=list(map(int,input().split()))
a=list(map(int,input().split()))
b=list(map(int,input().split()))
A=set(a);B=set(b)
if len(A)!=len(a) or len(B)!=len(b):
  print((0))
else:
  c=1;cn=0;cm=0
  for k in range(m*n,0,-1):
    if k in A and k in B:
      cn+=1;cm+=1
    elif k in A:
      c*=cm;cn+=1
    elif k in B:
      c*=cn;cm+=1
    else:
      c*=(cm*cn-m*n+k)
    if c==0:
      break
    c=c%(10**9+7)
  print(c)

# Optimized solution
n,m=list(map(int,input().split()))
a=list(map(int,input().split()))
b=list(map(int,input().split()))
A=set(a);B=set(b)
if len(A)!=len(a) or len(B)!=len(b):
  print((0))
else:
  c=1;cn=0;cm=0
  for k in range(m*n,0,-1):
    if k in A and k in B:
      cn+=1;cm+=1
    elif k in A:
      c*=cm;cn+=1
    elif k in B:
      c*=cn;cm+=1
    else:
      c*=cm*cn-m*n+k
    c=c%(10**9+7)
  print(c)
# Original solution
n,m=list(map(int,input().split()))
a=set(map(int,input().split()))
b=set(map(int,input().split()))
c=1;N=0;M=0
for k in range(m*n,0,-1):
  if k in a and k in b:
    N+=1;M+=1
  elif k in a:
    c*=M;N+=1
  elif k in b:
    c*=N;M+=1
  else:
    c*=M*N-m*n+k
  c=c%(10**9+7)
print(c)

# Optimized solution
n,m=list(map(int,input().split()))
a=set(map(int,input().split()))
b=set(map(int,input().split()))
c=1;N=0;M=0
for k in range(m*n,0,-1):
  if k in a and k in b:
    N+=1;M+=1
  elif k in a:
    c*=M;N+=1
  elif k in b:
    c*=N;M+=1
  else:
    c*=M*N-m*n+k
  c%=10**9+7
print(c)
# Original solution
n,m=list(map(int,input().split()))
a,b=set(map(int,input().split())),set(map(int,input().split()))
c=1;N=M=0
for k in range(m*n,0,-1):
  if k in a and k in b:
    N+=1;M+=1
  elif k in a:
    c*=M;N+=1
  elif k in b:
    c*=N;M+=1
  else:
    c*=M*N-m*n+k
print((c%(10**9+7)))

# Optimized solution
n,m=list(map(int,input().split()))
a,b=set(map(int,input().split())),set(map(int,input().split()))
c=1;N=M=0
for k in range(m*n,0,-1):
 A=k in a;B=k in b
 if A and B:N+=1;M+=1
 elif A:c*=M;N+=1
 elif B:c*=N;M+=1
 else:c*=M*N-m*n+k
 c%=10**9+7
print(c)
# Original solution
s,a,b=[set(map(int,input().split()))for j in[0]*3];c=1;N=M=0;x=max(a)
for k in range(x,0,-1):
 A=k in a;B=k in b
 if A and B:M+=1;N+=1
 elif A:c*=M;N+=1
 elif B:c*=N;M+=1
 else:c*=M*N-x+k
 c%=10**9+7
print(c)

# Optimized solution
s,a,b=[set(map(int,input().split()))for j in[0]*3];c=1;N=M=0;k=x=max(a)
while k:A=k in a;B=k in b;N+=A;M+=B;c*=[M*N-x+k,N,M,1][A*2+B];c%=10**9+7;k-=1
print(c)
# Original solution
import sys
input = sys.stdin.readline
from collections import *

N, M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))
sa = set(A)
sb = set(B)
row, col = 0, 0
ans = 1
MOD = 10**9+7

for i in range(N*M, 0, -1):
    if (i in sa) and (i in sb):
        row += 1
        col += 1
    elif (i not in sa) and (i in sb):
        ans *= col
        row += 1
    elif (i in sa) and (i not in sb):
        ans *= row
        col += 1
    else:
        ans *= row*col-(N*M-i)
    
    ans %= MOD

print(ans)

# Optimized solution
import sys
input = sys.stdin.readline
from collections import *

N, M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))
sa = set(A)
sb = set(B)
row, col = 0, 0
ans = 1
MOD = 10**9+7

for i in range(N*M, 0, -1):
    if (i in sa) and (i in sb):
        row += 1
        col += 1
    elif (i not in sa) and (i in sb):
        ans *= row
        col += 1
    elif (i in sa) and (i not in sb):
        ans *= col
        row += 1
    else:
        ans *= row*col-(N*M-i)
    
    ans %= MOD

print(ans)
# Original solution
from bisect import bisect
import sys

p = 10 ** 9 + 7
n, m = list(map(int, input().split()))
a = list(map(int, input().split()))
b = list(map(int, input().split()))

if n != len(set(a)) or m!= len(set(b)):
  print((0))
  sys.exit()
a.sort()
b.sort()

q = 1
for x in range(n*m, 0, -1):
  if x in a and x in b:
    q *= 1
  elif x in a:
    q = q * max(m - bisect(b, x), 0)  % p
  elif x in b:
    q = q * max(n - bisect(a, x), 0) % p
  else:
    u = bisect(a, x)
    v = bisect(b, x)
    q = q * (max((n-u) * (m-v) - (n * m - x), 0) % p) % p
print(q)
    
    
    

# Optimized solution
from bisect import bisect
import sys

p = 10 ** 9 + 7
n, m = list(map(int, input().split()))
a = list(map(int, input().split()))
b = list(map(int, input().split()))

if n != len(set(a)) or m!= len(set(b)):
  print((0))
  sys.exit()
A = set(a)
B = set(b)
a.sort()
b.sort()

q = 1
for x in range(n*m, 0, -1):
  if x in A and x in B:
    q *= 1
  elif x in A:
    q = q * max(m - bisect(b, x), 0)  % p
  elif x in B:
    q = q * max(n - bisect(a, x), 0) % p
  else:
    u = bisect(a, x)
    v = bisect(b, x)
    q = q * (max((n-u) * (m-v) - (n * m - x), 0) % p) % p
print(q)
# Original solution
import sys
N, M = list(map(int, input().split()))
A = [int(a) for a in input().split()]
B = [int(b) for b in input().split()]

A.sort(reverse=True)
B.sort(reverse=True)

if len(set(A))!=len(A) or len(set(B))!=len(B):
    print((0))
    sys.exit()

ans = 1
rows, columna = 0,0
mod = 10**9+7
for x in range(N*M, 0, -1):

    if x in A and x in B:
        rows += 1
        columna += 1

    elif x in A and not x in B:
        rows += 1
        ans = ans * (columna)

    elif x in B and not x in A:
        columna += 1
        ans = ans *(rows)

    else:
        ans = ans * (rows * columna -(N*M-x))

    ans %= mod

print((ans%(10**9+7)))


# Optimized solution
def solve():
    MOD = 10 ** 9 + 7
    N, M = list(map(int, input().split()))
    A = set(map(int, input().split()))
    B = set(map(int, input().split()))
    
    row, columun = 0, 0
    ans = 1
    for i in range(N * M, 0, -1):
        in_A = i in A
        in_B = i in B
        if in_A and in_B:
            row += 1
            columun += 1
        elif in_A:
            row += 1
            ans *= columun
        elif in_B:
            columun += 1
            ans *= row
        else:
            ans *= row * columun - (N * M - i)
        ans %= MOD
    print(ans)


if __name__ == '__main__':
    solve()
# Original solution
def sole():
    import sys
    N, M = list(map(int, input().split()))
    A = [int(a) for a in input().split()]
    B = [int(b) for b in input().split()]

    

    if len(set(A))!=len(A) or len(set(B))!=len(B):
        print((0))
        sys.exit()

    ans = 1
    rows, columna = 0,0
    mod = 10**9+7
    for x in range(N*M, 0, -1):

        if x in A and x in B:
            rows += 1
            columna += 1

        elif x in A and not x in B:
            rows += 1
            ans = ans * (columna)

        elif x in B and not x in A:
            columna += 1
            ans = ans *(rows)

        else:
            ans = ans * (rows * columna -(N*M-x))

        ans %= mod

    print((ans%(10**9+7)))



if __name__ == '__main__':
    sole()


# Optimized solution
def solve():
    MOD = 10 ** 9 + 7
    N, M = list(map(int, input().split()))
    A = set(map(int, input().split()))
    B = set(map(int, input().split()))
    
    row, columun = 0, 0
    ans = 1
    for i in range(N * M, 0, -1):
        in_A = i in A
        in_B = i in B
        if in_A and in_B:
            row += 1
            columun += 1
        elif in_A:
            row += 1
            ans *= columun
        elif in_B:
            columun += 1
            ans *= row
        else:
            ans *= row * columun - (N * M - i)
        ans %= MOD
    print(ans)


if __name__ == '__main__':
    solve()
# Original solution
mod = 10**9+7
n, m = list(map(int, input().split()))
a = sorted(list(map(int, input().split())), reverse=True)
b = sorted(list(map(int, input().split())), reverse=True)

if len(a) != len(set(a)) or len(b) != len(set(b)):
    print((0))
    exit()

c = 1
N = 0
M = 0
for k in range(n*m, 0, -1):
    if k in a and k in b:
        N += 1
        M += 1
    elif k in a:
        c *= M
        N += 1
    elif k in b:
        c *= N
        M += 1
    else:
        c *= M*N - (m*n-k)
    c %= mod

print(c)


# Optimized solution
mod = 10**9+7
n, m = list(map(int, input().split()))
a = sorted(list(map(int, input().split())), reverse=True)
b = sorted(list(map(int, input().split())), reverse=True)

if len(a) != len(set(a)) or len(b) != len(set(b)):
    print((0))
    exit()

a = set(a)
b = set(b)

c = 1
N = 0
M = 0
for k in range(n*m, 0, -1):
    if k in a and k in b:
        N += 1
        M += 1
    elif k in a:
        c *= M
        N += 1
    elif k in b:
        c *= N
        M += 1
    else:
        c *= M*N - (m*n-k)
    c %= mod

print(c)
# Original solution
MOD = int(1e9) + 7


def main():
    N, M = list(map(int, input().split()))
    A = list(map(int, input().split()))
    B = list(map(int, input().split()))
    sortA = sorted(A)
    sortB = sorted(B)
    for i in range(1, N):
        if sortA[i] == sortA[i-1]:
            print((0))
            return
    for j in range(1, M):
        if sortB[j] == sortB[j-1]:
            print((0))
            return
    retval = 1
    for num in range(N*M, 0, -1):
        icandidates = 0
        jcandidates = 0
        just = 1
        for i in range(N):
            if num == A[i]:
                icandidates = 1
                just = 0
                break
            if num <= A[i]:
                icandidates += 1
        for j in range(M):
            if num == B[j]:
                jcandidates = 1
                just = 0
                break
            if num <= B[j]:
                jcandidates += 1
        retval *= icandidates * jcandidates - (N*M - num) * just
        retval %= MOD

    print(retval)


if __name__ == "__main__":
    main()


# Optimized solution
MOD = int(1e9) + 7


def binsearch(num, ary):
    left = 0
    right = len(ary)
    while left < right:
        center = (left + right) // 2
        if num <= ary[center]:
            left = center + 1
        else:
            right = center
    return left


def main():
    N, M = list(map(int, input().split()))
    A = list(map(int, input().split()))
    B = list(map(int, input().split()))
    sortA = sorted(A, reverse=True)
    sortB = sorted(B, reverse=True)
    for i in range(1, N):
        if sortA[i] == sortA[i-1]:
            print((0))
            return
    for j in range(1, M):
        if sortB[j] == sortB[j-1]:
            print((0))
            return
    retval = 1
    for num in range(N*M, 0, -1):
        just = 1
        icandidates = binsearch(num, sortA)
        jcandidates = binsearch(num, sortB)
        if icandidates >= 1 and sortA[icandidates-1] == num:
            icandidates = 1
            just = 0
        if jcandidates >= 1 and sortB[jcandidates-1] == num:
            jcandidates = 1
            just = 0
#        print(icandidates, jcandidates, sortA, num)

        retval *= icandidates * jcandidates - (N*M - num) * just
        retval %= MOD

    print(retval)


if __name__ == "__main__":
    main()
# Original solution
N, M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

# 早期終了

if len(set(A)) != len(A):
    print((0))
    exit()
if len(set(B)) != len(B):
    print((0))
    exit()

# 高速化のため事前ソート

# A.sort(reverse=True)結局使わなかった
# B.sort(reverse=True)

n_A, n_B = 0, 0  # ある数よりも大きい要素数(単調増加)
# この問題は場合分けを思いつけるか、計算量を減らせるかにかかっている
# 与えられた集合の中にxょり大きい要素がいくつあるかという処理に大きく時間がかかっている
# これをn_Aとおくと、n_Aには単調増加性があることがすぐにわかる
# xをどんどん小さくしているからである。
# n_Aを逐一計算する代わりに、いままでの情報を使ってn_Aを求められると処理が高速化される
# A=[182, 181, 180, 179, 178, 176, 175, 169, 168, 167, 158, 151, 147, 129]とする(sorted)とすると、
# A[n_A]=xとなるn_Aがほしい。xが登場するまでのイテレーションでx_pre in Aとなる要素があるたび、その回数をカウントすればよい
#


def ret_n_given_x(x):
    global n_A, n_B
    flgA = True if x in A else False
    flgB = True if x in B else False
    # print(flgA, flgB)
    if flgA and flgB:
        n_A += 1  # 上記で解説した個数カウント
        n_B += 1  # xより大きな要素が何個あったかついでに記録できる
        return 1
    elif flgA:
        n_A += 1
        return n_B
    elif flgB:
        n_B += 1
        return n_A
    else:
        return (n_A * n_B)-(N*M-x)


MOD = 10**9 + 7
ans = 1
for x in range(N * M, 0, -1):
    ans *= ret_n_given_x(x)
    ans %= MOD
    # print(x, ans, ret_n_given_x(x))
    if ans == 0:
        break

print((int(ans)))


# Optimized solution
N, M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

# 早期終了

if len(set(A)) != len(A):
    print((0))
    exit()
if len(set(B)) != len(B):
    print((0))
    exit()

# 高速化のため事前ソート

A.sort(reverse=True)
B.sort(reverse=True)

n_A, n_B = 0, 0  # ある数よりも大きい要素数(単調増加)
# この問題は場合分けを思いつけるか、計算量を減らせるかにかかっている
# 与えられた集合の中にxょり大きい要素がいくつあるかという処理に大きく時間がかかっている
# これをn_Aとおくと、n_Aには単調増加性があることがすぐにわかる
# xをどんどん小さくしているからである。
# n_Aを逐一計算する代わりに、いままでの情報を使ってn_Aを求められると処理が高速化される
# A=[182, 181, 180, 179, 178, 176, 175, 169, 168, 167, 158, 151, 147, 129]とする(sorted)とすると、
# A[n_A]=xとなるn_Aがほしい。xが登場するまでのイテレーションでx_pre in Aとなる要素があるたび、その回数をカウントすればよい
#


def ret_n_given_x(x):
    global n_A, n_B
    flgA = False
    flgB = False
    for a in A[n_A:]:
        if a == x:
            flgA = True
            break
    for a in B[n_B:]:
        if a == x:
            flgB = True
            break
    if flgA and flgB:
        n_A += 1  # 上記で解説した個数カウント
        n_B += 1  # xより大きな要素が何個あったかついでに記録できる
        return 1
    elif flgA:
        n_A += 1
        return n_B
    elif flgB:
        n_B += 1
        return n_A
    else:
        return (n_A * n_B)-(N*M-x)


MOD = 10**9 + 7
ans = 1
for x in range(N * M, 0, -1):
    ans *= ret_n_given_x(x)
    ans %= MOD
    # print(x, ans, ret_n_given_x(x))
    if ans == 0:
        break

print((int(ans)))
# Original solution
n, m = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

mod = 10**9+7

SA = set(A)
SB = set(B)
A.sort()
B.sort()

if len(SA) != len(A) or len(SB) != len(B):
    print((0))
    exit()

ans = 1
import bisect
for i in reversed(list(range(1, n*m+1))):
    if i in SA and i in SB:
        ans *= 1
    elif i in SA:
        j = bisect.bisect_left(B, i)
        ans *= m-j
    elif i in SB:
        j = bisect.bisect_left(A, i)
        ans *= n-j
    else:
        j = bisect.bisect_left(A, i)
        k = bisect.bisect_left(B, i)
        ans *= (n-j)*(m-k) - (n*m-i)
    ans %= mod
print(ans)

# Optimized solution
n, m = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

A.sort()
B.sort()

SA = set(A)
SB = set(B)

if len(A) != len(SA):
    print((0))
    exit()

if len(B) != len(SB):
    print((0))
    exit()

ans = 1
mod = 10**9+7
import bisect
for i in reversed(list(range(1, n*m+1))):
    if i in SA and i in SB:
        ans *= 1
    elif i in SA and i not in SB:
        k = bisect.bisect_left(B, i)
        ans *= m-k
        ans %= mod
    elif i not in SA and i in SB:
        j = bisect.bisect_left(A, i)
        ans *= n-j
        ans %= mod
    else:
        j = bisect.bisect_left(A, i)
        k = bisect.bisect_left(B, i)
        ans *= (n-j)*(m-k)-(n*m-i)
        ans %= mod
    #print(ans)
print((ans%mod))
# Original solution
N, M = (list(map(int, input().split())))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

C = 1
A.sort(reverse=True)
B.sort(reverse=True)

aloop = 0
bloop = 0

if len(set(A)) != len(A) or len(set(B)) != len(B):
    C = 0

else:
    for k in range(N * M, 0, -1):
        if C == 0:
            break
        if k in A and k in B:
            continue
        elif (k in A and k not in B):
            C *= len([x for x in B if x > k])
        elif (k not in A and k in B):
            C *= len([x for x in A if x > k])
        else:
            C *= (len([x for x in A if x > k]) *
                  len([x for x in B if x > k]) - (N * M - k))

        C %= (10**9+7)

print(C)

# Optimized solution
N, M = (list(map(int, input().split())))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

C = 1
A.sort(reverse=True)
B.sort(reverse=True)

aloop = 0
bloop = 0

if len(set(A)) != len(A) or len(set(B)) != len(B):
    C = 0

else:
    for k in range(N * M, 0, -1):
        if aloop < N and bloop < M and k == A[aloop] and k == B[bloop]:
            aloop += 1
            bloop += 1
        elif aloop < N and k == A[aloop]:
            C *= bloop
            aloop += 1
        elif bloop < M and k == B[bloop]:
            C *= aloop
            bloop += 1
        else:
            C *= (aloop * bloop - (N * M - k))

        C = C % (10**9+7)
print(C)
# Original solution
N,M=list(map(int,input().split()))
Y=[0]*N*M
X=[0]*N*M
z=1
for a in map(int,input().split()):
	if Y[-a]:z=0
	Y[-a]=1
for b in map(int,input().split()):
	if X[-b]:z=0
	X[-b]=1
h=w=0
MD=10**9+7
for i in range(N*M):
	z*=[h*w-i,h,w,1][Y[i]*2+X[i]]
	z%=MD
	h+=Y[i]
	w+=X[i]
print(z)


# Optimized solution
s,a,b=[set(map(int,input().split()))for j in[0]*3];c=1;N=M=0;k=x=max(a)
while k:A=k in a;B=k in b;N+=A;M+=B;c*=[M*N-x+k,N,M,1][A*2+B];c%=10**9+7;k-=1
print(c)
# Original solution
N,M = list(map(int, input().split()))
A = list(map(int, input().split()))
B = list(map(int, input().split()))

mod = 10**9+7

a = 0
b = 0
ans = 1

for i in range(N*M,0,-1):
  #print(i,a,b,ans)
  if i in A and i in B:
    ans = ans
    a += 1
    b += 1
  elif i in A: # i not in B
    ans *= b
    ans %= mod
    a+=1
  elif i in B:
    ans *= a
    ans %= mod
    b+=1
  else:
    if a*b - (N*M - i) <= 0:
      print((0))
      break
    else:
      ans *= a*b - (N*M - i)
      ans %= mod
      
else:
  print(ans)
    
    
  


# Optimized solution
N,M = list(map(int, input().split()))
A = set(list(map(int, input().split())))
B = set(list(map(int, input().split())))

mod = 10**9+7

a = 0
b = 0
ans = 1

for i in range(N*M,0,-1):
  #print(i,a,b,ans)
  if i in A and i in B:
    ans = ans
    a += 1
    b += 1
  elif i in A: # i not in B
    ans *= b
    ans %= mod
    a+=1
  elif i in B:
    ans *= a
    ans %= mod
    b+=1
  else:
    if a*b - (N*M - i) <= 0:
      print((0))
      break
    else:
      ans *= a*b - (N*M - i)
      ans %= mod
      
else:
  print(ans)
# Original solution
def double_landscape(N: int, M: int, A: list, B: list) -> int:
    if not (is_unique(A) and is_unique(B)):
        return 0

    count = 1
    for x in range(N * M + 1, 0, -1):
        availables = 0
        if x in A and x in B:
            availables = 1
        elif x in A:
            availables = sum(b > x for b in B)
        elif x in B:
            availables = sum(a > x for a in A)
        else:
            used = (N * M - x)
            availables = sum(a > x and b > x for a in A for b in B)
            availables -= used

        if availables == 0:
            return 0

        count *= availables
        count %= 10**9 + 7

    return count


def is_unique(l: list) -> bool:
    return len(l) == len(set(l))


if __name__ == "__main__":
    N, M = [int(s) for s in input().split()]
    A = [int(s) for s in input().split()]
    B = [int(s) for s in input().split()]

    print((double_landscape(N, M, A, B)))


# Optimized solution
def double_landscape(N: int, M: int, A: list, B: list) -> int:
    if not (is_unique(A) and is_unique(B)):
        return 0

    A = sorted(A, reverse=True)
    B = sorted(B, reverse=True)
    i_a, i_b = 0, 0

    count = 1
    NM = N*M
    for x in range(NM, 0, -1):
        availables = 0
        if i_a < N and i_b < M and x == A[i_a] and x == B[i_b]:
            availables = 1
            i_a += 1
            i_b += 1
        elif i_a < N and x == A[i_a]:
            availables = i_b
            i_a += 1
        elif i_b < M and x == B[i_b]:
            availables = i_a
            i_b += 1
        else:
            availables = i_a * i_b - (NM - x)

        if availables <= 0:
            return 0

        count *= availables
        count %= 10**9 + 7

    return count


def is_unique(l: list) -> bool:
    return len(l) == len(set(l))


if __name__ == "__main__":
    N, M = [int(s) for s in input().split()]
    A = [int(s) for s in input().split()]
    B = [int(s) for s in input().split()]

    print((double_landscape(N, M, A, B)))
# Original solution
N, M = list(map(int, input().split()))
a_list = tuple(map(int, input().split()))
b_list = tuple(map(int, input().split()))
mod = 10 ** 9 + 7

a_list = sorted(a_list, reverse=True)
b_list = sorted(b_list, reverse=True)
a_list.append(-1)
b_list.append(-1)
ans = 1
a_i = 0
b_i = 0
for i in range(N*M, 0, -1):
    if i == a_list[a_i] and i == b_list[b_i]:
        a_i += 1
        b_i += 1
    elif i == a_list[a_i]:
        a_i += 1
        ans *= b_i
    elif i == b_list[b_i]:
        b_i += 1
        ans *= a_i
    else:
        ans *= (a_i*b_i - (N * M - i))
print((ans % mod))



# Optimized solution
N, M = list(map(int, input().split()))
a_list = tuple(map(int, input().split()))
b_list = tuple(map(int, input().split()))
mod = 10 ** 9 + 7

a_list = sorted(a_list, reverse=True)
b_list = sorted(b_list, reverse=True)
a_list.append(-1)
b_list.append(-1)
ans = 1
a_i = 0
b_i = 0
for i in range(N*M, 0, -1):
    if i == a_list[a_i] and i == b_list[b_i]:
        a_i += 1
        b_i += 1
    elif i == a_list[a_i]:
        a_i += 1
        ans *= b_i
        ans %= mod
    elif i == b_list[b_i]:
        b_i += 1
        ans *= a_i
        ans %= mod
    else:
        ans *= (a_i*b_i - (N * M - i))
        ans %= mod
print((ans % mod))