#include <stdio.h>
#include <assert.h>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <array>
#include <vector>
#include <queue>
#include <set>
#include <cmath>
#include <iomanip>
//#include <unordered_map>
//#include <unordered_set>
//#include <boost/container/static_vector.hpp>
//#include <boost/unordered_set.hpp>
//#include <boost/unordered_map.hpp>
//#include <unistd.h>

long long pow_mod(long long x, long long n, long long mod_num) {
    long long res = 1;
    while (n > 0) {
        if (n & 1) { res = (res * x) % mod_num; }
        x = (x * x) % mod_num;
        n = (n >> 1);
    }
    return res;
}

class Combi_Num {
    public:
    long long mod_num;
    std::vector<long long> factorial, factorial_inv, inv;
    Combi_Num() {}
    Combi_Num(const int n, const long long mod_num_in) {
        mod_num = mod_num_in;
        factorial.resize(n+1, 0);
        factorial_inv.resize(n+1, 0);
        inv.resize(n+1, 0);
        factorial[0] = 1;
        factorial_inv[0] = 1;
        inv[0] = 1;
        for (int i = 1; i <= n; i++) {
            factorial[i] = (factorial[i-1] * i) % mod_num;
            inv[i] = pow_mod(i, mod_num - 2, mod_num);
            factorial_inv[i] = (factorial_inv[i-1] * inv[i]) % mod_num;
        }
    }

    long long combi(const int n, const int r) {
        return (factorial[n] * ((factorial_inv[r] * factorial_inv[n-r]) % mod_num)) % mod_num;
    }

    long long perm(const int n, const int r) {
        if (r == 0) { return 1; }
        return (factorial[n] * factorial_inv[n-r]) % mod_num;
    }
};

const int MAX_N = 1050;
const long long MOD = (long long)1000000007;
Combi_Num combi_num = Combi_Num(MAX_N*MAX_N, MOD);

int N, M;
int A[MAX_N], B[MAX_N];

long long solve() {
    for (int i = 1; i <= N; i++) {
        if (A[i] == A[i+1]) {
            return 0;
        }
    }
    for (int i = 1; i <= M; i++) {
        if (B[i] == B[i+1]) {
            return 0;
        }
    }

    int height = 0;
    int width = 0;
    int cnt = 0;
    int prev_num = N * M + 1;
    long long ret = 1;
    while (height < N || width < M) {
        int area_num = width * height - cnt;
        if (A[height+1] == B[width+1]) {
            int number_num = prev_num - A[height+1] - 1;
            if (number_num > area_num) {
                return 0;
            }
            //std::cout << "che:" << area_num << " " << number_num << std::endl;
            ret = (ret * combi_num.perm(area_num, number_num)) % MOD;
            height++;
            width++;
            cnt += number_num + 1;
            prev_num = A[height];
        } else if (A[height+1] > B[width+1]) {
            int number_num = prev_num - A[height+1] - 1;
            if (number_num > area_num) {
                return 0;
            }
            ret = (ret * combi_num.perm(area_num, number_num)) % MOD;
            ret = (ret * width) % MOD;
            height++;
            cnt += number_num + 1;
            prev_num = A[height];
        } else {
            int number_num = prev_num - B[width+1] - 1;
            if (number_num > area_num) {
                return 0;
            }
            ret = (ret * combi_num.perm(area_num, number_num)) % MOD;
            ret = (ret * height) % MOD;
            cnt += number_num + 1;
            width++;
            prev_num = B[width];
        }
        //std::cout << "check:" << height << " " << width << " " << cnt << " " << area_num << " " << ret << std::endl;
    }
    ret = ret * combi_num.factorial[N*M-cnt];
    ret = ret % MOD;
    return ret;
}

int main(int argc, char **argv) {
    std::cin >> N >> M;
    
    for (int i = 1; i <= N; i++) {
        std::cin >> A[i];
    }

    for (int i = 1; i <= M; i++) {
        std::cin >> B[i];
    }

    std::sort(A + 1, A + N + 1, std::greater<int>());
    std::sort(B + 1, B + M + 1, std::greater<int>());

    A[N+1] = 0;
    B[M+1] = 0;

    std::cout << solve() << std::endl;
    

    return 0;
}


Measured memory_bytes: 26112