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);
    }
};


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 ans = 1;
   ll cnt = 0;
   ll R = 0,B = 0,G = 0;
   for(int i = 0;i < N;i++){
       if(R == B && B == G && A[i] == R){
           R++;
           ans *= 3;
           ans %= MOD;
       }else if(R == B && A[i] == R){
           R++;
           ans *= 2;
           ans %= MOD;
       }else if(B == G && A[i] == B){
           B++;
           ans *= 2;
           ans %= MOD;
       }else if(R == G && R == A[i]){
           G++;
           ans *= 2;
           ans %= MOD;
       }else if(R == A[i]){
           R++;
       }else if(B == A[i]){
           B++;
       }else if(G == A[i]){
           G++;
       }
   }
   cout << ans << endl;
}