#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

using tpl = tuple<int, int, int>;
typedef pair<int,int> pii;

void fastStream(){cin.tie(0);std::ios_base::sync_with_stdio(0);}


// 以下コピー
const int MAX_FACT = 2000000;
const int mod = 1000000000 + 7;
ll fact[MAX_FACT];

ll pow_mod(ll a,ll n){
  ll cur=1;
  ll mul=a;
  while(n){
    if(n%2)cur=(cur*mul)%mod;
    mul=(mul*mul)%mod;
    n/=2;
  }
  return cur;
}

ll div_mod(int a){
  return pow_mod(a,mod-2);
}

// factを前計算
void calcFact(){
  fact[0]=1;
  for(int i=1;i<MAX_FACT;i++)
    fact[i]=(fact[i-1]*i)%mod;
}

// aCbのmodを計算
// 計算量はO(log(fact[a])+log(fact[a-b]))程度
ll comb(ll a,ll b){
  if(a<0||b<0)return 0;
  else if(a<b)return 0;
  else if(b==0)return 1;
  ll res=fact[a];
  res=(res*div_mod(fact[b]))%mod;
  res=(res*div_mod(fact[a-b]))%mod;
  return res;
}


int N, M;
int A[1010];
int B[1010];
bool f[1010][1010];
bool is_used[1010*1010];

int solve(){
    calcFact();

    map<int, int> sta;
    for(int i = 0; i < N; i++){
        if(sta.count(A[i])){
            return 0;
        }
        sta[A[i]] = i;
    }
    map<int, int> stb;
    for(int i = 0; i < M; i++){
        if(stb.count(B[i])){
            return 0;
        }
        stb[B[i]] = i;
    }


    for(int i = 0; i < M; i++){
        if(sta.count(B[i])){
            int col = i;
            int row = sta[B[i]];
            // 両方に出る要素
            f[row][col] = true;
            is_used[B[i]] = true;
            // cout << row << " " << col << endl;
        }
    }

    vector<pair<int, pair<bool, int> > > v;
    // map<int, pair<bool, int> > m;
    // 順番に行と列を処理していく
    for(int i = 0; i < N; i++){
        v.push_back(make_pair(A[i], make_pair(true, i)));
    }
    for(int i = 0; i < M; i++){
        v.push_back(make_pair(B[i], make_pair(false, i)));
    }
    sort(v.begin(), v.end());
    
    int now = 1;
    int usable = 0;
    ll res = 1;
    for(auto p : v){
        int num = p.first;
        bool is_row = p.second.first;
        int row_or_col = p.second.second;
        // nowからnumまで値を数える
        for(int i = now; i <= num; i++){
            if(!is_used[i]){
                usable++;
                // is_used[i] = true;
            }
        }
        now = num + 1;

        int use = 0;
        if(is_row){
            int row = row_or_col;
            for(int col = 0; col < M; col++){
                if(!f[row][col]){
                    f[row][col] = true;
                    use++;
                }
            }
        }
        else{
            int col = row_or_col;
            for(int row = 0; row < N; row++){
                if(!f[row][col]){
                    f[row][col] = true;
                    use++;
                }
            }
        }

        // usable個から埋める個数を選ぶ
        if(usable < use){
            return 0;
        }
        
        // ここの値が使用済み
        if(is_used[num]){
            (res *= comb(usable, use)) %= mod;
            (res *= fact[use]) %= mod;
        }
        else{
            // comb
            (res *= comb(usable - 1, use - 1)) %= mod;
            (res *= fact[use]) %= mod;
        }

        usable -= use;
    }

    return res;
}


int main(){

    cin >> N >> M;
    for(int i = 0; i < N; i++) cin >> A[i];
    for(int i = 0; i < M; i++) cin >> B[i];
    // A[i] 間、B[i]間で重複がある場合は0
    // A[i]とB[j]で同じ要素がある場合、[i,j]はその要素になる
    // 最も小さい数から処理していく？

    cout << solve() << endl;
    
    return 0;
}


Measured memory_bytes: 17024