use std::io::*;
use std::ops::*;
use std::str::FromStr;
use utils::*;

pub fn main() {
    let i = stdin();
    let mut o = Vec::new();
    run(i.lock(), &mut o);
    stdout().write_all(&o).unwrap();
}

fn run<R: BufRead, W: Write>(i: R, o: &mut W) {
    let mut i = CpReader::new(i);
    let (n, m) = i.read2::<usize, usize>();
    let a = i.read_vec::<usize>(n);
    let b = i.read_vec::<usize>(m);

    writeln!(o, "{}", solve(a, b)).unwrap();
}
fn solve(mut a: Vec<usize>, mut b: Vec<usize>) -> usize {
    let mut used = 0;
    a.sort();
    a.reverse();

    b.sort();
    b.reverse();
    for i in 1..a.len() {
        if a[i - 1] == a[i] {
            return 0;
        }
    }
    for i in 1..b.len() {
        if b[i - 1] == b[i] {
            return 0;
        }
    }

    let mut r = Mod::new(1);
    while !a.is_empty() || !b.is_empty() {
        if let (Some(a0), Some(b0)) = (a.pop(), b.pop()) {
            let (n, c) = if a0 == b0 {
                (a0, a.len() + b.len())
            } else if a0 < b0 {
                b.push(b0);
                r *= b.len();
                (a0, b.len() - 1)
            } else {
                a.push(a0);
                r *= a.len();
                (b0, a.len() - 1)
            };
            used += 1;
            if used + c > n {
                return 0;
            }
            for _ in 0..c {
                r *= n - used;
                used += 1;
            }
        } else {
            return 0;
        }
    }
    r.0
}

mod utils {
    use super::*;

    pub struct CpReader<R: BufRead> {
        r: R,
        s: String,
    }

    macro_rules! fn_read {
        { $f:ident($($t:ident),*) } => {
            #[allow(dead_code)]
            pub fn $f<$($t: FromStr),*>(&mut self) -> ($($t),*) {
                let i = &mut self.read_line().split(' ');
                ($(read_next::<$t,_>(i)),*)
            }
        };
    }

    impl<R: BufRead> CpReader<R> {
        pub fn new(r: R) -> Self {
            CpReader {
                r: r,
                s: String::new(),
            }
        }
        pub fn read_line(&mut self) -> &str {
            self.s.clear();
            self.r.read_line(&mut self.s).unwrap();
            self.s.trim()
        }

        fn_read! { read2(T1, T2) }
        fn_read! { read3(T1, T2, T3) }
        fn_read! { read4(T1, T2, T3, T4) }
        fn_read! { read5(T1, T2, T3, T4, T5) }

        pub fn read_vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
            self.read_line()
                .split(' ')
                .take(n)
                .map(|x| x.parse().ok().unwrap())
                .collect()
        }
    }
    fn read_next<'a, T: FromStr, I: Iterator<Item = &'a str>>(i: &mut I) -> T {
        i.next().unwrap().parse().ok().unwrap()
    }

    #[derive(Clone, Copy)]
    pub struct Mod(pub usize);

    use std::fmt;
    impl fmt::Debug for Mod {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{:?}", self.0)
        }
    }

    const MOD_BASE: usize = 1000000007;
    const MOD_INV_POW: usize = 1000000005;

    impl Mod {
        pub fn new(n: usize) -> Self {
            Mod(n % MOD_BASE)
        }
        pub fn pow(self, mut exp: usize) -> Self {
            let mut b = self;
            let mut r = Mod(1);
            while exp != 0 {
                if exp % 2 == 1 {
                    r *= b;
                }
                exp /= 2;
                b = b * b;
            }
            r
        }
        pub fn inverse_element(self) -> Self {
            self.pow(MOD_INV_POW)
        }
    }

    macro_rules! mod_op {
        (($ot:ident, $f:ident), ($ot_a:ident, $f_a:ident), $($rhs:ty : $e:expr,)*) => {
            $(
            impl $ot<$rhs> for Mod {
                type Output = Self;
                fn $f(self, rhs: $rhs) -> Self {
                    ($e)(self, rhs)
                }
            }
            impl $ot_a<$rhs> for Mod {
                fn $f_a(&mut self, rhs: $rhs) {
                    *self = ($e)(*self, rhs)
                }
            }
            )*
        }
    }

    mod_op!(
        (Add, add),
        (AddAssign, add_assign),
        Mod : |l: Mod, r: Mod| Mod::new(l.0 + r.0),
        usize : |l: Mod, r: usize| l + Mod::new(r),
    );

    mod_op!(
        (Mul, mul),
        (MulAssign, mul_assign),
        Mod : |l: Mod, r: Mod| Mod::new(l.0 * r.0),
        usize : |l: Mod, r: usize| l * Mod::new(r),
    );

    mod_op!(
        (Sub, sub),
        (SubAssign, sub_assign),
        Mod : |l: Mod, r: Mod| Mod::new(MOD_BASE + l.0 - r.0),
        usize : |l: Mod, r: usize| l - Mod::new(r),
    );

    mod_op!(
        (Div, div),
        (DivAssign, div_assign),
        Mod : |l: Mod, r: Mod| l * r.inverse_element(),
        usize : |l: Mod, r: usize| l / Mod::new(r),
    );

    pub trait Zero: Add<Output = Self> + Sized + Copy {
        fn zero() -> Self;
    }
    pub trait One: Zero {
        fn one() -> Self;
    }

    macro_rules! impl_zero {
        ($t:ty, $e:expr) => {
            impl Zero for $t {
                fn zero() -> Self {
                    $e
                }
            }
        }
    }
    macro_rules! impl_one {
        ($t:ty, $e1:expr, $e0:expr) => {
            impl One for $t {
                fn one() -> Self {
                    $e1
                }
            }
            impl_zero!($t, $e0);
        };
    }

    impl_one!(usize, 1, 0);
    impl_one!(u32, 1, 0);
    impl_one!(i32, 1, 0);
    impl_one!(f64, 1.0, 0.0);
    impl_one!(Mod, Mod(1), Mod(0));
}


Measured memory_bytes: 4352