Problem:
Score : 900 points

Problem Statement

You are developing frog-shaped robots, and decided to race them against each other.

First, you placed N robots onto a number line.
These robots are numbered 1 through N.
The current coordinate of robot i is x_i.
Here, all x_i are integers, and 0 < x_1 < x_2 < ... < x_N.

You will repeatedly perform the following operation:

Select a robot on the number line. Let the coordinate of the robot be x. Select the destination coordinate, either x-1 or x-2, that is not occupied by another robot. The robot now jumps to the selected coordinate.

When the coordinate of a robot becomes 0 or less, the robot is considered finished and will be removed from the number line immediately.
You will repeat the operation until all the robots finish the race.

Depending on your choice in the operation, the N robots can finish the race in different orders.
In how many different orders can the N robots finish the race?
Find the answer modulo 10^9+7.

Constraints

2 ≤ N ≤ 10^5

x_i is an integer.

0 < x_1 < x_2 < ... < x_N ≤ 10^9

Partial Score

In a test set worth 500 points, N ≤ 8.

Input

The input is given from Standard Input in the following format:

N
x_1 x_2 ... x_N

Output

Print the number of the different orders in which the N robots can finish the race, modulo 10^9+7.

Sample Input 1

3
1 2 3

Sample Output 1

4

There are four different orders in which the three robots can finish the race:

(Robot 1 → Robot 2 → Robot 3)

(Robot 1 → Robot 3 → Robot 2)

(Robot 2 → Robot 1 → Robot 3)

(Robot 2 → Robot 3 → Robot 1)

Sample Input 2

3
2 3 4

Sample Output 2

6

There are six different orders in which the three robots can finish the race:

(Robot 1 → Robot 2 → Robot 3)

(Robot 1 → Robot 3 → Robot 2)

(Robot 2 → Robot 1 → Robot 3)

(Robot 2 → Robot 3 → Robot 1)

(Robot 3 → Robot 1 → Robot 2)

(Robot 3 → Robot 2 → Robot 1)

For example, the order (Robot 3 → Robot 2 → Robot 1) can be achieved as shown in the figure below:

Sample Input 3

8
1 2 3 5 7 11 13 17

Sample Output 3

10080

Sample Input 4

13
4 6 8 9 10 12 14 15 16 18 20 21 22

Sample Output 4

311014372

Remember to print the answer modulo 10^9+7.
This case is not included in the test set for the partial score.

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Numerics;
using static System.Math;
using static System.Array;
using static AtCoder.IO_ShortCut;
using static AtCoder.Tool;
namespace AtCoder
{
    class AC
    {
        const int MOD = 1000000007;
        //const int MOD = 998244353;
        const int INF = int.MaxValue / 2;
        const long SINF = long.MaxValue / 2;
        const double EPS = 1e-8;
        static readonly int[] dI = { 0, 1, 0, -1, 1, -1, -1, 1 };
        static readonly int[] dJ = { 1, 0, -1, 0, 1, 1, -1, -1 };
        static List<List<int>> G = new List<List<int>>();
        //static List<List<Edge>> G = new List<List<Edge>>();
        //static List<Edge> E = new List<Edge>();
        static void Main(string[] args)
        {
            //var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            //Console.SetOut(sw);

            int N = Int;
            var x = _ReadSplitInt;
            var fac = new long[100101];
            fac[0] = 1;
            for(var i = 0; i < 100100; i++)
            {
                fac[i + 1] = (fac[i] * (i + 1)) % MOD;
            }
            long ans = 1;
            long num = 0;
            for(var i = 0; i < N; i++)
            {
                num++;
                if (num > (x[i] + 1) / 2)
                {
                    ans *= num;
                    num--;
                }
            }
            OutL((ans * fac[num]) % MOD);

            //Console.Out.Flush();
        }
        struct Edge
        {
            public int from;

            public int to;
            public long dist;
            public Edge(int t, long c)
            {
                from = -1;
                to = t;
                dist = c;
            }
            public Edge(int f, int t, long c)
            {
                from = f;
                to = t;
                dist = c;
            }
        }
    }
    
    static class IO_ShortCut
    {
        public static string[] _ReadSplit => Console.ReadLine().Split();
        public static int[] _ReadSplitInt => ConvertAll(Console.ReadLine().Split(), int.Parse);
        public static long[] _ReadSplitLong => ConvertAll(Console.ReadLine().Split(), long.Parse);
        public static double[] _ReadSplit_Double => ConvertAll(Console.ReadLine().Split(), double.Parse);
        public static string Str => Console.ReadLine();
        public static int Int => int.Parse(Console.ReadLine());
        public static long Long => long.Parse(Console.ReadLine());
        public static double Double => double.Parse(Console.ReadLine());
        public static T Conv<T>(string input) => (T)Convert.ChangeType(input, typeof(T));
        public static void Input<T>(out T a) => a = Conv<T>(Console.ReadLine());
        public static void Input<T, U>(out T a, out U b)
        { var q = _ReadSplit;a = Conv<T>(q[0]);b = Conv<U>(q[1]); }
        public static void Input<T, U, V>(out T a, out U b, out V c)
        { var q = _ReadSplit;a = Conv<T>(q[0]);b = Conv<U>(q[1]);c = Conv<V>(q[2]); }
        public static void Input<T, U, V, W>(out T a, out U b, out V c, out W d)
        { var q = _ReadSplit; a = Conv<T>(q[0]); b = Conv<U>(q[1]); c = Conv<V>(q[2]);d = Conv<W>(q[3]); }

        public static void OutL(object s) => Console.WriteLine(s);
        public static void Out_Sep<T>(IEnumerable<T> s) => Console.WriteLine(string.Join(" ", s));
        public static void Out_Sep<T>(IEnumerable<T> s, string sep) => Console.WriteLine(string.Join($"{sep}", s));
        public static void Out_Sep(params object[] s) => Console.WriteLine(string.Join(" ", s));
        public static void Out_One(object s) => Console.Write($"{s} ");
        public static void Out_One(object s, string sep) => Console.Write($"{s}{sep}");
        public static void Endl() => Console.WriteLine();
    }
    public static class Tool
    {
        static public void Initialize<T>(ref T[] array, T initialvalue)
        {
            array = ConvertAll(array, x => initialvalue);
        }
        static public void Swap<T>(ref T a, ref T b)
        {
            T keep = a;
            a = b;
            b = keep;
        }
        static public void Display<T>(T[,] array2d, int n, int m)
        {
            for (var i = 0; i < n; i++)
            {
                for (var j = 0; j < m; j++)
                {
                    Console.Write($"{array2d[i, j]} ");
                }
                Console.WriteLine();
            }
        }
        static public long LPow(int a, int b) => (long)Pow(a, b);
        static public bool Bit(long x, int dig) => ((1L << dig) & x) != 0;
    }
    class Modulo
    {
        private int M;
        private readonly long[] m_facs;
        public long Mul(long a, long b)
        {
            return ((a * b) % M);
        }
        public Modulo(long n, int m)
        {
            M = m;
            m_facs = new long[n + 1];
            m_facs[0] = 1;
            for (long i = 1; i <= n; ++i)
            {
                m_facs[i] = Mul(m_facs[i - 1], i);
            }
        }
        public long Fac(long n)
        {
            return m_facs[n];
        }
        public long Pow(long a, long m)
        {
            switch (m)
            {
                case 0:
                    return 1L;
                case 1:
                    return a;
                default:
                    long p1 = Pow(a, m / 2);
                    long p2 = Mul(p1, p1);
                    return ((m % 2) == 0) ? p2 : Mul(p2, a);
            }
        }
        public long Div(long a, long b)
        {
            return Mul(a, Pow(b, M - 2));
        }
        public long Ncr(long n, long r)
        {
            if (n < r) { return 0; }
            if (n == r) { return 1; }
            long res = Fac(n);
            res = Div(res, Fac(r));
            res = Div(res, Fac(n - r));
            return res;
        }
    }
}