Problem:
Score: 500 points

Problem Statement

N people are standing in a queue, numbered 1, 2, 3, ..., N from front to back. Each person wears a hat, which is red, blue, or green.

The person numbered i says:

"In front of me, exactly A_i people are wearing hats with the same color as mine."

Assuming that all these statements are correct, find the number of possible combinations of colors of the N people's hats.

Since the count can be enormous, compute it modulo 1000000007.

Constraints

1 \leq N \leq 100000

0 \leq A_i \leq N-1

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 A_2 A_3 ... A_N

Output

Print the number of possible combinations of colors of the N people's hats, modulo 1000000007.

Sample Input 1

6
0 1 2 3 4 5

Sample Output 1

3

We have three possible combinations, as follows:

Red, Red, Red, Red, Red, Red

Blue, Blue, Blue, Blue, Blue, Blue

Green, Green, Green, Green, Green, Green

Sample Input 2

3
0 0 0

Sample Output 2

6

Sample Input 3

54
0 0 1 0 1 2 1 2 3 2 3 3 4 4 5 4 6 5 7 8 5 6 6 7 7 8 8 9 9 10 10 11 9 12 10 13 14 11 11 12 12 13 13 14 14 15 15 15 16 16 16 17 17 17

Sample Output 3

115295190

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using static Exter;
using System.Linq;
using System.Numerics;
#if DEBUG
#else
using console = System.Console;
#endif

public class App
{
    public static void Main(string[] args)
    {
        int n = (int)readarr[0];
        int[] color = new int[3];
        long l = 1;
        foreach(var val in readarr)
        {
            int c = 0;
            for(int i = 0;i<3;i++)
            {
                if(color[i] == val)
                {
                    if(c == 0)
                        color[i]++;
                    c++;
                }
            }
            l *= c;
            l %= 1000000007;
        }
        cout = l;
    }
    public static long Gcd(long a, long b)=>a > b ? GcdRecursive(a, b) : GcdRecursive(b, a);
    private static long GcdRecursive(long a, long b){if(b == 0) return a; return GcdRecursive(b, a % b);}
}
public class RollingHash
{
    long[] h;
    long m = 2147483647;
    int b = 524287;
    Power baser;
    public RollingHash(string s)
    {
        baser = new Power(b);
        h = new long[s.Length];
        h[0] = 0;
        for(int i = 1;i < s.Length;i++)
        {
            h[i] = (h[i-1] * b + s[i]) % m;
        }
    }
    public long Calc(int l,int r)
    {
        cout = h[r];
        cout = h[l] * baser.GetEntry(r-l-1);
        return 0;
    }
}
public class PriorityQueue<T> : IEnumerable<T> where T : IComparable
        {
            List<T> buffer = new List<T>();
            static void PushHeap(List<T> array, T elem)
            {
                int n = array.Count;
                array.Add(elem);
 
                while (n != 0)
                {
                    int i = (n - 1) / 2;
                    if (array[n].CompareTo(array[i]) < 0)
                    {
                        T tmp = array[n]; array[n] = array[i]; array[i] = tmp;
                    }
                    n = i;
                }
            }
            static void PopHeap(List<T> array)
            {
                int n = array.Count - 1;
                array[0] = array[n];
                array.RemoveAt(array.Count - 1);
 
                for (int i = 0, j; (j = 2 * i + 1) < n;)
                {
                    if ((j != n - 1) && (array[j].CompareTo(array[j + 1]) > 0))
                        j++;
                    if (array[i].CompareTo(array[j]) > 0)
                    {
                        T tmp = array[j]; array[j] = array[i]; array[i] = tmp;
                    }
                    i = j;
                }
            }
            public int Count
            {
                get
                {
                    return buffer.Count;
                }
            }
            public void Push(T elem)
            {
                PushHeap(this.buffer, elem);
            }
            public T Peek()
            {
                return buffer[0];
            }
 
            public T Pop()
            {
                T a = buffer[0];
                PopHeap(this.buffer);
                return a;
            }
            public IEnumerator<T> GetEnumerator()
            {
                var v = new List<T>(buffer);
                while(v.Count != 0)
                {
                    yield return v[0];
                    PopHeap(v);
                }
            }
            IEnumerator IEnumerable.GetEnumerator()
            {
                return this.GetEnumerator();
            }
        }
public class Power
    {
        public int Base;
        private List<long> Value = new List<long>();
        public Power(int v)
        {
            if(v==1)
                new ArgumentOutOfRangeException();
            long prev = -1;
            long g = v;
            Base = v;
            
            while(g > prev)
            {
                Value.Add(g);
                prev = g;
                g *= g;
            }
        }
        public long GetEntry(int exponent)
        {
            long s = 1;
            for(int i = 0;(1<<i)<=exponent;i++)
            {
                if((exponent & (1<<i)) != 0)
                {
                    s *= Value[i];
                }
            }
            return s;
        }
    }
public static class Exter
{
    public static IEnumerable<long> PrimeFactors(long n)
    {
        int i = 2;
        long tmp = n;

        while (i * i <= n)
        {
            if(tmp % i == 0){
                tmp /= i;
                yield return i;
            }else{
                i++;
            }
        }
        if(tmp != 1) yield return tmp;
    }
    public class LoopArray<T>
    {
        public readonly int Length;
        private T[] arr;
        public LoopArray(int Capacity)
        {
            Length = Capacity;
        }
        public LoopArray(T[] ar)
        {
            arr = new T[ar.Length];
            Array.Copy(ar,arr,ar.Length);
        }
    }
    public class Point
    {
        public Point(int cx, int cy)
        {
            x = cx;
            y = cy;
        }
        public int x;
        public int y;
    }
    public static IEnumerable<Result> ListAll<T1,T2,Result>(IEnumerable<T1> a,IEnumerable<T2> b,Func<T1,T2,Result> f)
    {
        foreach(var v in a)
        {
            foreach(var w in b)
               yield return f(v,w);
        }
    }
    public static IEnumerable<Result> ListAll<T1,T2,Result>(IEnumerable<T1> a,IEnumerable<T2> b,Func<T1,T2,Result> f,Func<T1,T2,bool> s)
    {
        foreach(var v in a)
        {
            foreach(var w in b)
               if(s(v,w)) yield return f(v,w);
        }
    }
    public static int ToInt(this long v)=>(int)v;
    public static int ToInt(this string v)=>int.Parse(v);
    public static int Max(params int[] p)=>p.Max();
    public static long Max(params long[] p)=>p.Max();
    public static int Min(params int[] p)=>p.Min();
    public static long Min(params long[] p)=>p.Min();
    public static int Gcd(int a, int b)=>a > b ? GcdRecursive(a, b) : GcdRecursive(b, a);
    private static int GcdRecursive(int a, int b)=>b == 0 ? a : GcdRecursive(b, a % b);
    public static object cout
    {
        set
        {
            console.Write(value.ToString());
            console.WriteLine();
            
        }
    }
    public static void ToCout<t>(this IEnumerable<t> v)
    {
        cout = string.Join(",",v);
    }
    public static long[] readarr
    {
        get 
        {
            preadarr = console.ReadLine().Split().Select(s=>long.Parse(s)).ToArray();
            return preadarr;
        }
    }
    public static long[] preadarr;
}


#if DEBUG
public static class console
{
    static int cursorLine = 0;
    static readonly string[] cin = System.IO.File.ReadAllLines("Input.txt");
    static public string ReadLine()
    { 
        if(cursorLine == cin.Length)
            cout = "Out";
        return cin[cursorLine++];
    }
    static public void WriteLine()
    {
        Console.WriteLine();
    }
    static public void WriteLine<T>(T input)
    {
        Console.WriteLine(input);
    }
    static public void Write<T>(T input)
    {
        Console.Write(input);
    }
    static public void WriteLine(string s,params object[] arr)
    {
        Console.WriteLine(s,arr);
    }
}
#endif