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 C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace ARC076C
{
    class Program
    {
        static long Reconciled(long n, long m)
        {
            if (Math.Abs(m - n) >= 2)
            {
                // 隣り合わない組み合わせが存在しない
                return 0;
            }

            // nPn * mPm
            var mod = new Modulo();

            var ans = 1L;
            // nPn
            for (long i = 1; i <= n; i++)
            {
                ans = mod.Mul(ans, i);
            }

            // mPm
            for (long i = 1; i <= m; i++)
            {
                ans = mod.Mul(ans, i);
            }

            // 同じ数だけいるなら、どちらを先頭とするかで組み合わせが増える
            if (n == m)
            {
                ans = mod.Mul(ans, 2);
            }

            return ans;
        }

        static void Solve()
        {
            var n = Input.NextLong();
            var m = Input.NextLong();

            Console.WriteLine(Reconciled(n, m));
        }

        /// <summary>
        /// Mを法とする数値
        /// </summary>
        class Modulo
        {
            public long M { get; private set; }
            private bool mIsPrime;

            public Modulo(long m = (long)1e9 + 7)
            {
                this.M = m;
                this.mIsPrime = isPrime(m);
            }

            public long Add(long a, long b)
            {
                return (a + b) % this.M;
            }

            public long Sub(long a, long b)
            {
                return (a + this.M - b) % this.M;
            }

            public long Mul(long a, long b)
            {
                return ((a % this.M) * (b % this.M)) % this.M;
            }

            public long Power(long x, long y)
            {
                switch (y)
                {
                    case 0: return 1;
                    case 1: return x;

                    default:
                        long z1 = Power(x, y / 2);
                        long z2 = Mul(z1, z1);

                        if ((y % 2) == 0)
                        {
                            return z2;
                        }
                        else
                        {
                            return Mul(z2, x);
                        }
                }
            }

            public long Div(long a, long b)
            {
                if (!this.mIsPrime)
                {
                    throw new ArgumentException();
                }

                return Mul(a, Power(b, this.M - 2));
            }

            /// <summary>
            /// 素数か
            /// </summary>
            /// <param name="x"></param>
            /// <returns></returns>
            static bool isPrime(long x)
            {
                if (x < 2)
                {
                    return false;
                }
                if (x == 2)
                {
                    return true;
                }
                if ((x % 2) == 0)
                {
                    return false;
                }

                long rx = (long)(Math.Sqrt(x) + 1);
                for (long n = 3; n < rx; n += 2)
                {
                    if ((x % n) == 0)
                    {
                        return false;
                    }
                }

                return true;
            }
        }

        #region Competitive Template
        public static void Main(string[] args)
        {
            var needsFlushOutput = true;
            if (needsFlushOutput)
            {
                // 細かく出力しないようにする
                var sw = new System.IO.StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
                Console.SetOut(sw);
            }

            // 仮想的に標準入力をセットする
            // NextLine系を使っていると使えない
            //Input.SetText("");

            Solve();

            Console.Out.Flush();
        }

        static class Input
        {
            static char[] separator = { ' ' };
            public static bool IsEof { get; set; }
            static Queue<string> q { get; set; }

            static Input()
            {
                IsEof = false;
                q = new Queue<string>();
            }

            /// <summary>
            /// 入力予約
            /// </summary>
            /// <param name="items"></param>
            public static void SetText(IEnumerable<string> items)
            {
                foreach (var item in items)
                {
                    SetText(item);
                }
            }

            /// <summary>
            /// 入力予約
            /// </summary>
            /// <param name="s"></param>
            /// <returns></returns>
            public static bool SetText(string s)
            {
                if (s == null) return false;

                foreach (var elem in s.Trim().Split(separator, StringSplitOptions.RemoveEmptyEntries))
                {
                    q.Enqueue(elem);
                }

                return true;
            }

            /// <summary>
            /// 内部queueに入力からの値をsplitして格納する
            /// </summary>
            /// <returns></returns>
            static bool read()
            {
                var s = Console.ReadLine();
                if (s == null) return false;

                foreach (var elem in s.Trim().Split(separator, StringSplitOptions.RemoveEmptyEntries))
                {
                    q.Enqueue(elem);
                }

                if (!q.Any()) return read();

                return true;
            }

            /// <summary>
            /// 次のstringを一つ読み込む
            /// </summary>
            /// <returns></returns>
            public static string Next()
            {
                if (!q.Any())
                {
                    if (!read())
                    {
                        IsEof = true;
                        return "";
                    }
                }

                return q.Dequeue();
            }

            public static int NextInt() => int.Parse(Next());
            public static long NextLong() => long.Parse(Next());
            public static double NextDouble() => double.Parse(Next());

            public static List<string> Next(int n) => Enumerable.Range(0, n).Select(_ => Next()).ToList();
            public static List<int> NextInt(int n) => Next(n).Select(x => int.Parse(x)).ToList();
            public static List<long> NextLong(int n) => Next(n).Select(x => long.Parse(x)).ToList();
            public static List<double> NextDouble(int n) => Next(n).Select(x => double.Parse(x)).ToList();

            public static List<string> NextLine() => Console.ReadLine().Trim().Split(separator, StringSplitOptions.RemoveEmptyEntries).ToList();
            public static List<int> NextIntLine() => NextLine().Select(x => int.Parse(x)).ToList();
            public static List<long> NextLongLine() => NextLine().Select(x => long.Parse(x)).ToList();
            public static List<double> NextDoubleLine() => NextLine().Select(x => double.Parse(x)).ToList();
        }
        #endregion
    }
}