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++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>
using namespace std;

typedef long long  ll;

ll MOD = 1000000007;
ll INF = 100000000000000000;
int PI = 3.1415926535;

template<typename T>
void remove(std::vector<T>& vector, unsigned int index)
{
    vector.erase(vector.begin() + index);
}

using Graph = vector<vector<tuple<ll,ll,ll>>>;


struct UnionFind{
    vector<int> par;
    vector<int> rank;

    UnionFind(int N):par(N),rank(N){
        for(int i = 0;i < N;i++){
          par[i] = i;
          rank[i] = 0;
        }
    }

    int root(int x){
       while(x != par[x]){
        x =  par[x] = par[par[x]];
       }
       return x;
    }

    void unite(int x,int y){
        int rx = root(x);
        int ry = root(y);
        if(rx == ry)return;
        if(rank[x] > rank[y]){
          par[y] = rx;
        }
        if(rank[x] < rank[y]){
          par[rx] = ry;
        }else{
          par[ry] = rx;
          if(rank[x] == rank[y]){
            rank[rx]++;
          }
        }
    }

    bool same(int x,int y){
      return root(x) == root(y);
    }
};


ll modpow(ll a,ll n,ll m){//modpow(a,n,m) := a ^ n (mod m)
  ll res = 1;
  while(n > 0){
    if(n & 1)res = res * a % m;
    a = a * a % m;
    n >>= 1;
  }
  return res;
}

ll modinv(ll a,ll p){//modinv(a,p) := pを法とするaの逆元(※pは素数でなければならない)
    ll res = modpow(a,p-2,p);
    return res;
}

ll modCON(ll n,ll r,ll m){
   ll res = 1;
   for(int i = 1;i <= n;i++){
      res *= i;
      res %= m;
   }
   for(int i = 1;i <= r;i++){
      res *= modinv(i,m);
      res %= m;
   }
   for(int i = 1;i <= n-r;i++){
      res *= modinv(i,m);
      res %= m;
   }
   return res;
}


int main(){
   ll N;cin >> N;
   vector<ll> A(N);
   UnionFind F(N);
   for(int i = 0;i < N;i++){
       cin >> A[i];
   }
   for(int i = 0;i < N-1;i++){
       if(A[i] + 1 == A[i+1]){
           F.unite(i,i+1);
       }
   }
   ll cntR = 0,cntB = 0,cntG = 0;
   ll R = 0,B = 0,G = 0;
   for(int i = 0;i < N;i++){
       if(R == A[i]){
           R++;
           remove(A,i);
           i--;
           N--;
       }
   }
   for(int i = 0;i < N;i++){
       if(B == A[i]){
           B++;
           remove(A,i);
           i--;
           N--;
       }
   }
   for(int i = 0;i < N;i++){
       if(G == A[i]){
           G++;
           remove(A,i);
           i--;
           N--;
       }
   }
   //cout << R << B << G << endl;
   ll ans = modCON(N,R,MOD);
   ans *= modCON(N-R,B,MOD);
   ans %= MOD;
   //cout << ans << endl;
   if(R > 0 && B > 0 && G > 0){
       ans *=  1;
   }else if((R == 0 && B == 0) || (R == 0 && G == 0) || (G == 0 && B == 0)){
       ans *= 3;
   }else{
       ans *= 3;
   }
   cout << ans << endl;
}