use std::cmp;
use std::collections::BTreeSet;
use std::ops::{AddAssign, Sub};

const MOD: usize = 1e9 as usize + 7;

fn main() {
    let s = std::io::stdin();
    let mut sc = Scanner { reader: s.lock() };
    let n = sc.read();
    let m = sc.read();
    let mut a: Vec<usize> = sc.read_vec(n);
    let mut b: Vec<usize> = sc.read_vec(m);
    a.sort();
    a.reverse();
    b.sort();
    b.reverse();
    if a[0] != b[0] || a[0] != n * m {
        println!("0");
        return;
    }
    for i in 1..n {
        if a[i - 1] == a[i] {
            println!("0");
            return;
        }
    }
    for i in 1..m {
        if b[i - 1] == b[i] {
            println!("0");
            return;
        }
    }

    let a_set = a.iter().map(|&a| a).collect::<BTreeSet<_>>();
    let b_set = b.iter().map(|&a| a).collect::<BTreeSet<_>>();

    let mut v = vec![];
    for x in a_set.iter() {
        if b_set.contains(x) {
            v.push((*x, 0));
        } else {
            v.push((*x, 1));
        }
    }
    for x in b_set.iter() {
        if !a_set.contains(x) {
            v.push((*x, 2));
        }
    }
    v.sort();

    println!("{}", solve(n, m, v));
}

fn solve(mut n: usize, mut m: usize, v: Vec<(usize, usize)>) -> usize {
    let mut bit = FenwickTree::new(n * m + 1, 0);
    for &(v, is_a) in v.iter() {
        bit.add(v, 1);
    }

    let mut ans = 1;
    for &(v, is_a) in v.iter() {
        match is_a {
            0 => {
                // both
                let count = bit.sum_one(v + 1);
                if count > v {
                    return 0;
                }
                let selectable = v - count;
                if n == 0 || m == 0 {
                    return 0;
                }
                for i in 0..(n - 1 + m - 1) {
                    ans *= selectable - i;
                    ans %= MOD;
                }
                bit.add(0, n - 1 + m - 1);
                assert_eq!(bit.sum_one(v + 1), count + n - 1 + m - 1);
                n -= 1;
                m -= 1;
            }
            1 => {
                // is a

                ans *= m;
                ans %= MOD;
                if m == 0 {
                    return 0;
                }
                let count = bit.sum_one(v + 1);
                if v < count {
                    return 0;
                }

                let selectable = v - count;
                if selectable < m - 1 {
                    return 0;
                }
                for i in 0..(m - 1) {
                    ans *= selectable - i;
                    ans %= MOD;
                }
                bit.add(0, m - 1);
                assert_eq!(bit.sum_one(v + 1), count + m - 1);
                n -= 1;
            }
            2 => {
                // is b

                ans *= n;
                ans %= MOD;
                if n == 0 {
                    return 0;
                }
                let count = bit.sum_one(v + 1);
                if v < count {
                    return 0;
                }
                let selectable = v - count;
                if selectable < n - 1 {
                    return 0;
                }
                for i in 0..(n - 1) {
                    ans *= selectable - i;
                    ans %= MOD;
                }
                bit.add(0, n - 1);
                assert_eq!(bit.sum_one(v + 1), count + n - 1);
                m -= 1;
            }
            _ => unreachable!(),
        }
    }

    ans
}

pub struct Combination {
    fact: Vec<usize>,
    inv_fact: Vec<usize>,
    modulo: usize,
}

impl Combination {
    pub fn new(max: usize, modulo: usize) -> Combination {
        let mut inv = vec![0; max + 1];
        let mut fact = vec![0; max + 1];
        let mut inv_fact = vec![0; max + 1];
        inv[1] = 1;
        for i in 2..(max + 1) {
            inv[i] = inv[modulo % i] * (modulo - modulo / i) % modulo;
        }
        fact[0] = 1;
        inv_fact[0] = 1;
        for i in 0..max {
            fact[i + 1] = fact[i] * (i + 1) % modulo;
        }
        for i in 0..max {
            inv_fact[i + 1] = inv_fact[i] * inv[i + 1] % modulo;
        }
        Combination {
            fact: fact,
            inv_fact: inv_fact,
            modulo: modulo,
        }
    }

    pub fn get(&self, x: usize, y: usize) -> usize {
        assert!(x >= y);
        self.fact[x] * self.inv_fact[y] % self.modulo * self.inv_fact[x - y] % self.modulo
    }

    pub fn h(&self, n: usize, r: usize) -> usize {
        self.get(n + r - 1, r)
    }
}
pub struct FenwickTree<T> {
    n: usize,
    data: Vec<T>,
    init: T,
}

impl<T: Copy + AddAssign + Sub<Output = T>> FenwickTree<T> {
    /// Constructs a new `FenwickTree`. The size of `FenwickTree` should be specified by `size`.
    pub fn new(size: usize, init: T) -> FenwickTree<T> {
        FenwickTree {
            n: size + 1,
            data: vec![init; size + 1],
            init: init,
        }
    }

    pub fn add(&mut self, k: usize, value: T) {
        let mut x = k;
        while x < self.n {
            self.data[x] += value;
            x |= x + 1;
        }
    }

    /// Returns a sum of range `[l, r)`
    pub fn sum(&self, l: usize, r: usize) -> T {
        self.sum_one(r) - self.sum_one(l)
    }

    /// Returns a sum of range `[0, k)`
    pub fn sum_one(&self, k: usize) -> T {
        if k >= self.n {
            panic!("");
        }

        let mut result = self.init;
        let mut x = k as i32 - 1;
        while x >= 0 {
            result += self.data[x as usize];
            x = (x & (x + 1)) - 1;
        }

        result
    }
}
pub struct Scanner<R> {
    reader: R,
}

impl<R: std::io::Read> Scanner<R> {
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .reader
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n')
            .take_while(|&b| b != b' ' && b != b'\n')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn read_vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}


Measured memory_bytes: 12540