#include <iostream>
#include <algorithm>
#include <vector>
#include<string>
#include <set>
#include <map>
#include <queue>
#include <limits.h>
#include <bitset>
#include <cmath>

using namespace std;

#define rip(i, n, s) for (int i = (s);i < ( int )( n ); i++)
#define all(a) (a).begin(), (a).end()
typedef long long ll;
typedef pair<int,int> P;
struct modint {
	long long num;
	long long p;
	modint() {
		num = 0;
		p = 1000000007;
	}
	modint(int x) {
		p = 1000000007;
		num = (long long)x%p;
	}
	modint(long long x) {
		p = 1000000007;
		num = x % p;
	}
	modint operator*(const long long &other) {
		modint ret;
		ret.p = p;
		ret.num = (num*(other%p)) % p;
		return ret;
	}
	void operator*=(const long long &other) {
		num = (num*other) % p;
	}
};

int main(){
    int n,m;
    cin >> n >> m;
    vector<P> da(n+m);
    rip(i,n,0){
        cin >> da[i].first;
        da[i].second=1;
    }
    rip(i,m,0){
        cin >> da[i+n].first;
        da[i+n].second=0;
    }
	set<int> ch;
	rip(i,n,0){
		if(ch.count(da[i].first)){
			cout << 0 << endl;
			return 0;
		}
		else{
			ch.insert(da[i].first);
		}
	}
	ch.clear();
	rip(i,m,0){
		if(ch.count(da[i+n].first)){
			cout << 0 << endl;
			return 0;
		}
		else{
			ch.insert(da[i+n].first);
		}
	}
    modint ans(1);
    int now=n*m,h=0,w=0,cr=0;
    sort(all(da));
    reverse(all(da));
    int co=0;
	while(co<n+m){
		//printf("%d %d %d %d %d %lld\n",now,co,h,w,cr,ans.num);
		if(now<=0){
			cout << 0 << endl;
			return 0;
		}
		if(da[co].first==now){
			if(co<n*m-1){
				if(da[co+1].first==now){
					h++;
					w++;
					cr++;
					co++;
				}
				else{
					if(da[co].second){
						ans*=w;
						h++;
					}
					else{
						ans*=h;
						w++;
					}
					cr++;
				}
			}
			else{
				if(da[co].second){
					ans*=w;
					h++;
				}
				else{
					ans*=h;
					w++;
				}
			}
			co++;
		}
		else{
			if((h*w)-cr>0){
			ans*=(h*w)-cr;
			cr++;
			}
			else{
				cout << 0 << endl;
				return 0;
			}
		}
		now--;
	}
	rip(i,now+1,1){
		ans*=i;
	}
	cout << ans.num << endl;
}
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <utility>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <functional>
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vector<ll>> vvl;
typedef pair<ll, ll> P;
typedef vector<vector<P>> vvP;
#define rep(i, n) for(ll i = 0; i < n; i++)
#define exrep(i, a, b) for(ll i = a; i <= b; i++)
#define out(x) cout << x << endl
#define exout(x) printf("%.10f\n", x)
#define chmax(x, y) x = max(x, y)
#define chmin(x, y) x = min(x, y)
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define pb push_back
#define re0 return 0
const ll mod = 1000000007;
const ll INF = 1e16;
const ll MAX_N = 100010;

int main() {
    ll h, w;
    cin >> h >> w;

    vl a(h);
    set<ll> st1;
    vl v1(h*w+1);  // v1[i] : aの中でi以上の数の個数
    rep(i, h) {
        cin >> a[i];
        st1.insert(a[i]);
        v1[a[i]]++;
    }

    vl b(w);
    set<ll> st2;
    vl v2(h*w+1);  // v2[i] : bの中でi以上の数の個数
    rep(i, w) {
        cin >> b[i];
        st2.insert(b[i]);
        v2[b[i]]++;
    }

    if(st1.size() != h || st2.size() != w) {
        out(0);
        re0;
    }

    for(ll i = h*w; i >= 2; i--) {
        v1[i-1] += v1[i];
        v2[i-1] += v2[i];
    }   

    ll ans = 1;
    ll cnt = 0;
    for(ll x = h*w; x >= 1; x--) {
        if(st1.find(x) != st1.end() && st2.find(x) != st2.end()) {
            ans *= 1;
        }
        else if(st1.find(x) != st1.end() && st2.find(x) == st2.end()) {
            ans *= v2[x];
        }
        else if(st1.find(x) == st1.end() && st2.find(x) != st2.end()) {
            ans *= v1[x];
        }
        else {
            ans *= max(0LL, v1[x]*v2[x] - cnt);
        }
        ans %= mod;
        cnt++;
    }

    out(ans);
    re0;
}