#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
// #include <boost/multiprecision/cpp_int.hpp> 

#define gc getchar//_unlocked
#define pc putchar//_unlocked
#define ll long long
#define ld long double
#define pb push_back
#define mp make_pair
#define pp pair<int,int>
#define ppl pair<ll,ll>
#define bigint boost::multiprecision::cpp_int
#define finp ios_base::sync_with_stdio(0);cin.tie(0);
#define bc __builtin_popcountll
#define afor(i,a,b) for(int i=a;i<=b;++i)
#define bfor(i,a,b) for(int i=a;i>=b;--i)
#define vi vector<int>
#define vpp vector<pp>
#define vll vector<ll>
#define fr first
#define se second

using namespace std;
using namespace __gnu_pbds;

char putnb[20];
void putn(ll n) {if(!n)pc('0');if(n<0)pc('-'),n=0-n;int pi=0;while(n)putnb[pi++]=(n%10)+'0',n/=10;while(pi)pc(putnb[--pi]);}
void sci(int *x) {register char c = gc();*x = 0;for(; (c<48)||(c>57);c = gc());for(; (c>47)&&(c<58);c = gc())*x = (int)((((*x)<<1) + ((*x)<<3)) + c - 48);}
void scll(ll *x)  {register char c = gc();*x = 0;for(; (c<48)||(c>57);c = gc());for(; (c>47)&&(c<58);c = gc())*x =  (ll)((((*x)<<1) + ((*x)<<3)) + c - 48);}
ll fp(ll a,ll b,ll c) {if(b==0)return 1%c; if(b==1)return a%c; ll ret=fp(a,b/2,c); ret=(ret*ret)%c; if(b&1)ret=(ret*a)%c; return ret;}

const ll mod=1e9 +7;
const ll mod2=1999999973;
const ll inf=1e18;
const int infs=1e9 + 1000;
const int N=100000;
const long double PI = acos(-1);

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

int n,m;
int A[1005];
int B[1005];
set<int,greater<int>> sr,sc;
vector<pp> vsr,vsc;
ll fact[1000005];
int main()
{
  fact[0] = 1;
  afor(i,1,1000000)
  {
    fact[i] = (fact[i-1] * (ll)i)%mod;
  }
  finp;
  cin>>n>>m;
  afor(i,1,n)
  {
    cin>>A[i];
    sr.insert(A[i]);
    vsr.pb({A[i],i});
  }
  afor(i,1,m)
  {
    cin>>B[i];
    sc.insert(B[i]);
    vsc.pb({B[i],i});
  }

  if(sr.size()<n || sc.size()<m)
  {
    cout<<"0";
    return 0;
  }

  sort(vsr.begin(),vsr.end());
  sort(vsc.begin(),vsc.end());
  ll ans = 1;
  ll rw = 0;
  ll cl = 0;
  ll sp = 0;
  set<int> doner,donec;
  bfor(i,n*m,1)
  {
    while(vsr.size() && vsr.back().fr>i)vsr.pop_back();
    while(vsc.size() && vsc.back().fr>i)vsc.pop_back();

    ll rback = -1;
    ll rpos = -1;
    if(vsr.size())rback = vsr.back().fr,rpos = vsr.back().se;
    ll cback = -1;
    ll cpos = -1;
    if(vsc.size())cback = vsc.back().fr,cpos = vsc.back().se;

   

    if(rback != i)//can only place within rw rows
    {
      if(cback != i)//can only place within cl rows
      {
        //sp++;
        ans*= max(0LL,(rw*cl - (n*m - i)));
        ans%= mod;
      }
      else //
      {
        assert(cl < m);
        if(donec.find(cpos) != donec.end())ans = 0;
        ans*= rw;
        ans%= mod;
        cl++;
        donec.insert(cpos);
      }
    }
    else 
    {
      if(cback != i)
      {
        assert(rw < n);
        if(doner.find(rpos) != doner.end())ans = 0;
        ans*= cl;
        ans%= mod;
        rw++;
        doner.insert(rpos);
      }
      else
      {
        //ans*= (n*m - cr*m - cl*n + cl*cr + mod)%mod;
        //ans%= mod;
        assert(rw<n && cl<m);
        if(donec.find(cpos) != donec.end())ans = 0;
        if(doner.find(rpos) != doner.end())ans = 0;
        cl++;
        rw++;
        donec.insert(cpos);
        doner.insert(rpos);
      }
    }
  }
//ans*= fact[sp];
//ans%= mod;
if(cl<m || rw<n)ans = 0;
  cout<<ans;
  
return 0;
}

Measured memory_bytes: 8320