Problem:
Score : 300 points

Problem Statement

Snuke has N dogs and M monkeys. He wants them to line up in a row.

As a Japanese saying goes, these dogs and monkeys are on bad terms. ("ken'en no naka", literally "the relationship of dogs and monkeys", means a relationship of mutual hatred.) Snuke is trying to reconsile them, by arranging the animals so that there are neither two adjacent dogs nor two adjacent monkeys.

How many such arrangements there are? Find the count modulo 10^9+7 (since animals cannot understand numbers larger than that).
Here, dogs and monkeys are both distinguishable. Also, two arrangements that result from reversing each other are distinguished.

Constraints

1 ≤ N,M ≤ 10^5

Input

Input is given from Standard Input in the following format:

N M

Output

Print the number of possible arrangements, modulo 10^9+7.

Sample Input 1

2 2

Sample Output 1

8

We will denote the dogs by A and B, and the monkeys by C and D. There are eight possible arrangements: ACBD, ADBC, BCAD, BDAC, CADB, CBDA, DACB and DBCA.

Sample Input 2

3 2

Sample Output 2

12

Sample Input 3

1 8

Sample Output 3

0

Sample Input 4

100000 100000

Sample Output 4

530123477

Solution in Rust (1.15.1) (judge verdict: Accepted)

/*------------------------------------------------------------------*/
/*------------------------- begin template -------------------------*/
/*------------------------------------------------------------------*/

// ref: tanakh <https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8>
// diff: using Parser
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut parser = Parser::from_str($s);
        input_inner!{parser, $($r)*}
    };
    (parser = $parser:ident, $($r:tt)*) => {
        input_inner!{$parser, $($r)*}
    };
    (new_stdin_parser = $parser:ident, $($r:tt)*) => {
        let stdin = std::io::stdin();
        let reader = std::io::BufReader::new(stdin.lock());
        let mut $parser = Parser::new(reader);
        input_inner!{$parser, $($r)*}
    };
    ($($r:tt)*) => {
        input!{new_stdin_parser = parser, $($r)*}
    };
}

macro_rules! input_inner {
    ($parser:ident) => {};
    ($parser:ident, ) => {};
    ($parser:ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($parser, $t);
        input_inner!{$parser $($r)*}
    };
}

macro_rules! read_value {
    ($parser:ident, ( $($t:tt),* )) => {
        ( $(read_value!($parser, $t)),* )
    };
    ($parser:ident, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($parser, $t)).collect::<Vec<_>>()
    };
    ($parser:ident, chars) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()
    };
    ($parser:ident, char_) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()[0]
    };
    ($parser:ident, usize1) => {
        read_value!($parser, usize) - 1
    };
    ($parser:ident, i64_) => {
        $parser.fast_i64()
    };
    ($parser:ident, usize_) => {
        $parser.fast_i64() as usize
    };
    ($parser:ident, usize1_) => {
        ($parser.fast_i64() - 1) as usize
    };
    ($parser:ident, $t:ty) => {
        $parser.next::<$t>().expect("Parse error")
    };
}

use std::io;
use std::io::BufRead;
use std::str;

// ref: tatsuya6502 <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e>
// ref: wariuni <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e#comment-7040a5ae96305e884eb9>
// diff: using std::io::BufRead::fill_buf()
pub struct Parser<R> {
    pub reader: R,
    buf: Vec<u8>,
    pos: usize,
}

impl Parser<io::Empty> {
    pub fn from_str(s: &str) -> Parser<io::Empty> {
        Parser {
            reader: io::empty(),
            buf: s.as_bytes().to_vec(),
            pos: 0,
        }
    }
}

impl<R: BufRead> Parser<R> {
    pub fn new(reader: R) -> Parser<R> {
        Parser {
            reader: reader,
            buf: vec![],
            pos: 0,
        }
    }
    pub fn update_buf(&mut self) {
        self.buf.clear();
        self.pos = 0;
        loop {
            let (len, complete) = {
                let buf2 = self.reader.fill_buf().unwrap();
                self.buf.extend_from_slice(buf2);
                let len = buf2.len();
                (len, buf2[len - 1] <= 0x20)
            };
            self.reader.consume(len);
            if complete {
                break;
            }
        }
    }
    pub fn next<T: str::FromStr>(&mut self) -> Result<T, T::Err> {
        loop {
            let mut begin = self.pos;
            while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                begin += 1;
            }
            let mut end = begin;
            while end < self.buf.len() && (self.buf[end] > 0x20) {
                end += 1;
            }
            if begin != self.buf.len() {
                self.pos = end;
                return unsafe { str::from_utf8_unchecked(&self.buf[begin..end]) }.parse::<T>();
            } else {
                self.update_buf();
            }
        }
    }
    pub fn fast_i64(&mut self) -> i64 {
        loop {
            let mut begin = self.pos;
            while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                begin += 1;
            }
            if begin == self.buf.len() {
                self.update_buf();
                continue;
            }
            let mut res = 0;
            let (is_positive, mut end) = match self.buf[begin] {
                b'+' => (true, begin + 1),
                b'-' => (false, begin + 1),
                _ => (true, begin),
            };
            while end < self.buf.len() && (self.buf[end] > 0x20) {
                res = res * 10 + (self.buf[end] as i64 - '0' as i64);
                end += 1;
            }
            if begin != self.buf.len() {
                self.pos = end;
                return if is_positive { res } else { -res };
            } else {
                self.update_buf();
            }
        }
    }
}

#[allow(unused_imports)]
use std::cmp::*;
use std::marker::PhantomData;
use std::ops::*;

pub trait ModP {
    fn as_u64() -> u64;
}

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug)]
pub struct Mod_1_000_000_007();
impl ModP for Mod_1_000_000_007 {
    fn as_u64() -> u64 {
        1_000_000_007
    }
}

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug)]
pub struct Mod_998_244_353();
impl ModP for Mod_998_244_353 {
    fn as_u64() -> u64 {
        998_244_353
    }
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub struct Modular<P: ModP + Copy>(u32, PhantomData<P>);

impl<P: ModP + Copy> Modular<P> {
    pub fn new(x: u32) -> Modular<P> {
        Modular((x as u64 % P::as_u64()) as u32, PhantomData)
    }
    pub fn pow(self, n: u64) -> Modular<P> {
        if n == 0 {
            return Modular(1, PhantomData);
        }
        let t = self.pow(n / 2);
        if n % 2 == 0 {
            t * t
        } else {
            t * t * self
        }
    }
    pub fn as_u32(self) -> u32 {
        self.0
    }
}

impl<P: ModP + Copy> Add for Modular<P> {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        let t = (self.0 + rhs.0) as u64;
        let u = if t < P::as_u64() { t } else { t - P::as_u64() };
        Modular(u as u32, PhantomData)
    }
}

impl<P: ModP + Copy> AddAssign for Modular<P> {
    fn add_assign(&mut self, rhs: Self) {
        *self = *self + rhs;
    }
}

impl<P: ModP + Copy> Sub for Modular<P> {
    type Output = Self;
    fn sub(self, rhs: Self) -> Self::Output {
        let t = if self.0 >= rhs.0 {
            self.0 as u64 - rhs.0 as u64
        } else {
            self.0 as u64 + P::as_u64() - rhs.0 as u64
        };
        assert!(t < P::as_u64());
        Modular(t as u32, PhantomData)
    }
}

impl<P: ModP + Copy> SubAssign for Modular<P> {
    fn sub_assign(&mut self, rhs: Self) {
        *self = *self - rhs;
    }
}

impl<P: ModP + Copy> Neg for Modular<P> {
    type Output = Modular<P>;
    fn neg(self) -> Modular<P> {
        Modular((P::as_u64() - self.0 as u64) as u32, PhantomData)
    }
}

impl<P: ModP + Copy> Mul for Modular<P> {
    type Output = Self;
    fn mul(self, rhs: Self) -> Self::Output {
        Modular(
            ((self.0 as u64 % P::as_u64()) * (rhs.0 as u64 % P::as_u64()) % P::as_u64()) as u32,
            PhantomData,
        )
    }
}

impl<P: ModP + Copy> MulAssign for Modular<P> {
    fn mul_assign(&mut self, rhs: Self) {
        *self = *self * rhs;
    }
}

impl<P: ModP + Copy> Div for Modular<P> {
    type Output = Self;
    fn div(self, rhs: Self) -> Self::Output {
        if rhs.0 == 0 {
            loop {}
        }
        assert!(rhs.0 != 0);
        self * rhs.pow(P::as_u64() - 2)
    }
}

pub fn gen_fact_table<P: ModP + Copy>(n: usize) -> Vec<Modular<P>> {
    let mut res = vec![Modular::<P>::new(1); n + 1];
    for i in 0..n {
        res[i + 1] = res[i] * Modular::<P>::new((i + 1) as u32);
    }
    res
}

pub fn gen_inv_table<P: ModP + Copy>(n: usize) -> Vec<Modular<P>> {
    let mut res = vec![Modular::<P>::new(0); n + 1];
    res[1] = Modular::<P>::new(1);
    for i in 2..n + 1 {
        res[i] =
            -res[P::as_u64() as usize % i] * Modular::<P>::new((P::as_u64() / i as u64) as u32);
    }
    res
}

fn main() {
    input! {
        new_stdin_parser = parser,
    }
    let res = solve(&mut parser);
    print!("{}", res);
}

/*------------------------------------------------------------------*/
/*-------------------------- end template --------------------------*/
/*------------------------------------------------------------------*/

type Mod = Modular<Mod_1_000_000_007>;

use std::fmt::Write;
fn solve<R: BufRead>(parser: &mut Parser<R>) -> String {
    let mut buf = String::new();
    input! {
        parser = parser,
        n: usize,
        m: usize,
    }
    let facts = gen_fact_table(max(n, m) + 1);
    let res = if n == m {
        Mod::new(2) * facts[n] * facts[m]
    } else if (n as i64 - m as i64).abs() == 1 {
        facts[n] * facts[m]
    } else {
        Mod::new(0)
    };
    writeln!(buf, "{}", res.as_u32());
    buf
}