#include <iostream>
#include <string.h>

#define MAXN 5001
#define L 1000000007

using namespace std;

int d[MAXN][MAXN] = {0};

char s[MAXN], t[MAXN];

int main()
{
//    freopen("input.txt", "r", stdin);

    cin >> s;
    cin >> t;

    int ans = 0;

    for (int i = 0; i < strlen(s); i++)
    {
        for (int j = 0; j < strlen(t); j++)
        {
            d[i + 1][j + 1] = d[i + 1][j];
            if (s[i] == t[j]) d[i + 1][j + 1] = (d[i + 1][j + 1] + d[i][j] + 1) % L;
//            cout << d[i + 1][j + 1] << " ";
        }
        ans = (ans + d[i + 1][strlen(t)]) % L;
//        cout << endl;
    }

    cout << ans;

    return 0;
}


#include <iostream>
#include <string>

#define MAXN 5001
#define L 1000000007

using namespace std;

int d[MAXN][MAXN] = {0};

string s, t;

int main()
{
//    freopen("input.txt", "r", stdin);

    cin >> s;
    cin >> t;

    int ans = 0;

    int n = s.length();
    int m = t.length();

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            d[i + 1][j + 1] = d[i + 1][j];
            if (s[i] == t[j]) d[i + 1][j + 1] = (d[i + 1][j + 1] + d[i][j] + 1) % L;
//            cout << d[i + 1][j + 1] << " ";
        }
        ans = (ans + d[i + 1][m]) % L;
//        cout << endl;
    }

    cout << ans;

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <string>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <ctime>

using namespace std;

#define f first
#define s second
#define pb push_back
#define mp make_pair
#define forit(s) for(__typeof(s.begin()) it = s.begin(); it != s.end(); it ++)
#define N 100100
#define all(a) a.begin(), a.end()
#define ll long long
#define pii pair <int, int>
#define vi vector <int>
#define sz(a) (int)a.size()

const int inf = (int)(1e9);
const int mod = inf + 7;
const double pi = acos(-1.0);
const double eps = 1e-9;

string s, t;
ll ans[5500][5500];

int main () {

    #ifdef LOCAL
    freopen("a.in", "r", stdin);
    freopen("a.out", "w", stdout);
    #endif

    getline(cin, s);
    getline(cin, t);

    int n = s.length(), m = t.length();

    for(int i = n - 1; i >= 0; i --) {
        for(int j = m - 1; j >= 0; j --) {
            ans[i][j] = ans[i][j + 1];
            if(s[i] == t[j]) ans[i][j] += 1ll + ans[i + 1][j + 1];
        }
    }

    ll res = 0;

    for(int i = 0; i < n; i ++) res += ans[i][0];

    cout << res;

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <string>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <ctime>

using namespace std;

#define f first
#define s second
#define pb push_back
#define mp make_pair
#define forit(s) for(__typeof(s.begin()) it = s.begin(); it != s.end(); it ++)
#define N 100100
#define all(a) a.begin(), a.end()
#define ll long long
#define pii pair <int, int>
#define vi vector <int>
#define sz(a) (int)a.size()

const int inf = (int)(1e9);
const int mod = inf + 7;
const double pi = acos(-1.0);
const double eps = 1e-9;

string s, t;
int ans[5500][5500];

int main () {

    #ifdef LOCAL
    freopen("a.in", "r", stdin);
    freopen("a.out", "w", stdout);
    #endif

    getline(cin, s);
    getline(cin, t);

    int n = s.length(), m = t.length();

    for(int i = n - 1; i >= 0; i --) {
        for(int j = m - 1; j >= 0; j --) {
            if(j != m - 1) ans[i][j] = ans[i][j + 1];
            else ans[i][j] = 0;
            if(s[i] == t[j]) ans[i][j] += 1 + ans[i + 1][j + 1];
        }
    }

    int res = 0;

    for(int i = 0; i < n; i ++) res += ans[i][0];

    cout << res;

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <string>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <ctime>

using namespace std;

#define f first
#define s second
#define pb push_back
#define mp make_pair
#define forit(s) for(__typeof(s.begin()) it = s.begin(); it != s.end(); it ++)
#define N 100100
#define all(a) a.begin(), a.end()
#define ll long long
#define pii pair <int, int>
#define vi vector <int>
#define sz(a) (int)a.size()

const int inf = (int)(1e9);
const int mod = inf + 7;
const double pi = acos(-1.0);
const double eps = 1e-9;

string s, t;
int ans[5500][5500];

int main () {

    #ifdef LOCAL
    freopen("a.in", "r", stdin);
    freopen("a.out", "w", stdout);
    #endif

    getline(cin, s);
    getline(cin, t);

    int n = s.length(), m = t.length();

    for(int i = n - 1; i >= 0; i --) {
        for(int j = m - 1; j >= 0; j --) {
            if(j != m - 1) ans[i][j] = ans[i][j + 1];
            else ans[i][j] = 0;
            if(s[i] == t[j]) ans[i][j] += 1 + ans[i + 1][j + 1];
        }
    }

    ll res = 0;

    for(int i = 0; i < n; i ++) res += ans[i][0];

    cout << res;

    return 0;
}


#include <iostream>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <string>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <ctime>

using namespace std;

#define f first
#define s second
#define pb push_back
#define mp make_pair
#define forit(s) for(__typeof(s.begin()) it = s.begin(); it != s.end(); it ++)
#define N 100100
#define all(a) a.begin(), a.end()
#define ll long long
#define pii pair <int, int>
#define vi vector <int>
#define sz(a) (int)a.size()

const int inf = (int)(1e9);
const int mod = inf + 7;
const double pi = acos(-1.0);
const double eps = 1e-9;

string s, t;
int ans[5500][5500];

int main () {

    #ifdef LOCAL
    freopen("a.in", "r", stdin);
    freopen("a.out", "w", stdout);
    #endif

    getline(cin, s);
    getline(cin, t);

    int n = s.length(), m = t.length();

    for(int i = n - 1; i >= 0; i --) {
        for(int j = m - 1; j >= 0; j --) {
            ans[i][j] = ans[i][j + 1];
            if(s[i] == t[j]) ans[i][j] = (ans[i][j] + 1ll + ans[i + 1][j + 1]) % mod;
        }
    }

    ll res = 0;

    for(int i = 0; i < n; i ++) res = (res + 0ll + ans[i][0]) % mod;

    cout << res;

    return 0;
}


#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <sstream>

using namespace std;
const int inf = (1 << 30) - 1;
typedef long long LL;
typedef pair <int, int> ii;
typedef vector <int> vi;
typedef vector <ii> vii;

#define pb push_back
#define debug(X) cout << "debug : " << #X << " = " << X << '\n'; //int,char,char[]
#define debugc(X,Y)  for( int VAR = 0; VAR < Y; VAR++) cout << "debugc : " << #X <<'[' << VAR << "]  = " << *(X+VAR) << '\n'; // int[], char[] c
#define debugstl(X)  for( int VAR = 0; VAR < X.size(); VAR++) cout << "debugstl : "<< #X << '[' << VAR << "] = " << X[VAR] << '\n';// stl vector,string
#define MOD 1000000007
#define maxn 5005
int main(){
	int dp[maxn];
	string s, t;
	cin >> s >> t;
	int n = s.size();
	int m = t.size();
/*
	for (int i = 0; i < m; ++i){
		for (int j = n - 1; j >= 0; --j){
			if (t[i] == s[j]){
				dp[j+1] = (dp[j+1] + dp[j] + 1) % MOD;
			}
		}
	}
*/
	for (int i = 0; i < m; ++i) {
		for (int j = n - 1; j > -1; --j) {
			if (s[j] == t[i]) {
				dp[j + 1] = (dp[j + 1] + dp[j] + 1) % MOD;
			}

		}
	}
	int ret = 0;
	for (int j = 0; j <= n; ++j) {
		ret = (ret + dp[j]) % MOD;
	}
	cout << ret << endl;
/*
	int ans = 0;
	for (int i = 0; i <= n; ++i)
		ans = (ans + dp[i]) % MOD;
	cout << ans << endl;
*/
	return 0;
}


#include <iostream>
#include <cstring>
using namespace std;

#define MOD 1000000007
#define maxn 5005

int main() {
	int dp[maxn];
	memset (dp, 0, sizeof(dp));
//	for (int i = 0; i < 1000; i++) cout << dp[i];

	string s,t;
	cin >> s >> t;
	int n = s.size(), m = t.size();
	for (int i = 0; i < m; ++i) {
		for (int j = n - 1; j > -1; --j) {
			if (s[j] == t[i]) {
				dp[j + 1] = (dp[j + 1] + dp[j] + 1) % MOD;
			}
		}
	}
	int ret = 0;
	for (int j = 0; j <= n; ++j) {
		ret = (ret + dp[j]) % MOD;
	}
	cout << ret << endl;
	return 0;
}


#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <sstream>

using namespace std;
const int inf = (1 << 30) - 1;
typedef long long LL;
typedef pair <int, int> ii;
typedef vector <int> vi;
typedef vector <ii> vii;

#define pb push_back
#define debug(X) cout << "debug : " << #X << " = " << X << '\n'; //int,char,char[]
#define debugc(X,Y)  for( int VAR = 0; VAR < Y; VAR++) cout << "debugc : " << #X <<'[' << VAR << "]  = " << *(X+VAR) << '\n'; // int[], char[] c
#define debugstl(X)  for( int VAR = 0; VAR < X.size(); VAR++) cout << "debugstl : "<< #X << '[' << VAR << "] = " << X[VAR] << '\n';// stl vector,string
#define MOD 1000000007
#define maxn 5005
int main(){
	int dp[maxn];
	string s, t;
	cin >> s >> t;
	int n = s.size();
	int m = t.size();

	for (int i = 0; i < m; ++i){
		for (int j = n - 1; j >= 0; --j){
			if (t[i] == s[j]){
				dp[j+1] = (dp[j+1] + dp[j] + 1) % MOD;
			}
		}
	}
	int ans = 0;
	for (int i = 0; i <= n; ++i)
		ans = (ans + dp[i]) % MOD;
	cout << ans << endl;

	return 0;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <utility>
using namespace std;

#define mp(a,b) make_pair(a,b)

#define MOD 1000000007

int dp[5005];

char s[5005], t[5005];

int main() {
	cin >> s >> t;
	int n = strlen(s), m = strlen(t);
	for (int i = 0; i < m; ++i) {
		for (int j = n - 1; j > -1; --j) {
			if (s[j] == t[i]) {
				dp[j + 1] = (dp[j + 1] + dp[j] + 1) % MOD;
			}
		}
//		cout << t[i] << " ";
//		for (int k = 0; k < m; k++)cout << dp[k] << " "o;
//		cout << endl;
	}
	int ret = 0;
	for (int j = 0; j <= n; ++j) {
		ret = (ret + dp[j]) % MOD;
	}
	cout << ret << endl;
	return 0;
}


#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <sstream>

using namespace std;
const int inf = (1 << 30) - 1;
typedef long long LL;
typedef pair <int, int> ii;
typedef vector <int> vi;
typedef vector <ii> vii;

#define pb push_back
#define debug(X) cout << "debug : " << #X << " = " << X << '\n'; //int,char,char[]
#define debugc(X,Y)  for( int VAR = 0; VAR < Y; VAR++) cout << "debugc : " << #X <<'[' << VAR << "]  = " << *(X+VAR) << '\n'; // int[], char[] c
#define debugstl(X)  for( int VAR = 0; VAR < X.size(); VAR++) cout << "debugstl : "<< #X << '[' << VAR << "] = " << X[VAR] << '\n';// stl vector,string
#define MOD 1000000007
#define maxn 5005
int main(){
	int dp[maxn];
	string s, t;
	cin >> s >> t;
	int n = s.size();
	int m = t.size();
/*
	for (int i = 0; i < m; ++i){
		for (int j = n - 1; j >= 0; --j){
			if (t[i] == s[j]){
				dp[j+1] = (dp[j+1] + dp[j] + 1) % MOD;
			}
		}
	}
*/
	for (int i = 0; i < m; ++i) {
		for (int j = n - 1; j > -1; --j) {
			if (s[j] == t[i]) {
				dp[j + 1] = (dp[j + 1] + dp[j] + 1) % MOD;
			}

		}
	}

	int ans = 0;
	for (int i = 0; i <= n; ++i)
		ans = (ans + dp[i]) % MOD;
	cout << ans << endl;

	return 0;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <utility>
using namespace std;

#define MOD 1000000007

int dp[5005];

int main() {

	string s,t;
	cin >> s >> t;
	int n = s.size(), m = t.size();
	for (int i = 0; i < m; ++i) {
		for (int j = n - 1; j > -1; --j) {
			if (s[j] == t[i]) {
				dp[j + 1] = (dp[j + 1] + dp[j] + 1) % MOD;
			}
		}
	}
	int ret = 0;
	for (int j = 0; j <= n; ++j) {
		ret = (ret + dp[j]) % MOD;
	}
	cout << ret << endl;
	return 0;
}


#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <sstream>

using namespace std;
const int inf = (1 << 30) - 1;
typedef long long LL;
typedef pair <int, int> ii;
typedef vector <int> vi;
typedef vector <ii> vii;

#define pb push_back
#define debug(X) cout << "debug : " << #X << " = " << X << '\n'; //int,char,char[]
#define debugc(X,Y)  for( int VAR = 0; VAR < Y; VAR++) cout << "debugc : " << #X <<'[' << VAR << "]  = " << *(X+VAR) << '\n'; // int[], char[] c
#define debugstl(X)  for( int VAR = 0; VAR < X.size(); VAR++) cout << "debugstl : "<< #X << '[' << VAR << "] = " << X[VAR] << '\n';// stl vector,string
#define MOD 1000000007
#define maxn 5002
int main(){
	int dp[maxn];
	string s, t;
	cin >> s >> t;
	int n = s.size();
	int m = t.size();

	for (int i = 0; i < m; i++){
		for (int j = n - 1; j >= 0; j--){
			if (t[i] == s[j]){
				dp[j+1] = (dp[j+1] + dp[j] + 1) % MOD;
			}
		}
	}
	int ans = 0;
	for (int i = 0; i <= n; i++)
		ans = (ans + dp[i]) % MOD;
	cout << ans << endl;

	return 0;
}


#include <iostream>

using namespace std;

#define MOD 1000000007
#define maxn 5005

int main() {
	int dp[maxn];
	string s,t;
	cin >> s >> t;
	int n = s.size(), m = t.size();
	for (int i = 0; i < m; ++i) {
		for (int j = n - 1; j >= 0; --j) {
			if (s[j] == t[i]) {
				dp[j + 1] = (dp[j + 1] + dp[j] + 1) % MOD;
			}
		}
	}
	int ret = 0;
	for (int j = 0; j <= n; ++j) {
		ret = (ret + dp[j]) % MOD;
	}
	cout << ret << endl;
	return 0;
}


#include <iostream>

using namespace std;

#define MOD 1000000007
#define maxn 5005

int main() {
	int dp[maxn];
	string s,t;
	cin >> s >> t;
	int n = s.size(), m = t.size();
	for (int i = 0; i < m; ++i) {
		for (int j = n - 1; j > -1; --j) {
			if (s[j] == t[i]) {
				dp[j + 1] = (dp[j + 1] + dp[j] + 1) % MOD;
			}
		}
	}
	int ret = 0;
	for (int j = 0; j <= n; ++j) {
		ret = (ret + dp[j]) % MOD;
	}
	cout << ret << endl;
	return 0;
}


#include <iostream>

using namespace std;

#define MOD 1000000007
#define maxn 5005

	int dp[maxn];

int main() {
	string s,t;
	cin >> s >> t;
	int n = s.size(), m = t.size();
	for (int i = 0; i < m; ++i) {
		for (int j = n - 1; j > -1; --j) {
			if (s[j] == t[i]) {
				dp[j + 1] = (dp[j + 1] + dp[j] + 1) % MOD;
			}
		}
	}
	int ret = 0;
	for (int j = 0; j <= n; ++j) {
		ret = (ret + dp[j]) % MOD;
	}
	cout << ret << endl;
	return 0;
}


#include <iostream>
#include <cstring>
using namespace std;

#define MOD 1000000007
#define maxn 5005

int main() {
	int dp[maxn];
//	memset (dp, 0, sizeof(dp));
//	for (int i = 0; i < 1000; i++) cout << dp[i];

	string s,t;
	cin >> s >> t;
	int n = s.size(), m = t.size();
	for (int i = 0; i < m; ++i) {
		for (int j = n - 1; j > -1; --j) {
			if (s[j] == t[i]) {
				dp[j + 1] = (dp[j + 1] + dp[j] + 1) % MOD;
			}
		}
	}
	int ret = 0;
	for (int j = 0; j <= n; ++j) {
		ret = (ret + dp[j]) % MOD;
	}
	cout << ret << endl;
	return 0;
}


#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <utility>
using namespace std;

#define mp(a,b) make_pair(a,b)

#define MOD 1000000007

int dp[5005];

char s[5005], t[5005];

int main() {
	cin >> s >> t;
	int n = strlen(s), m = strlen(t);
	for (int i = 0; i < m; ++i) {
		for (int j = n - 1; j > -1; --j) {
			if (s[j] == t[i]) {
				dp[j + 1] = (dp[j + 1] + dp[j] + 1) % MOD;
			}
		}
		cout << t[i] << " ";
		for (int k = 0; k < m; k++)cout << dp[k] << " ";
		cout << endl;
	}
	int ret = 0;
	for (int j = 0; j <= n; ++j) {
		ret = (ret + dp[j]) % MOD;
	}
	cout << ret << endl;
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
using namespace std;
int n,m,f[5010][5010],ans,mod=1000000007;
char s[6000],t[6000];
int main(){
    scanf("%s%s",s+1,t+1);
    n=strlen(s+1);
    m=strlen(t+1);
    for(int i=0;i<=max(n,m);++i)f[0][i]=f[i][0]=1;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j){
            f[i][j]=f[i][j-1];
            if(s[i]==t[j])f[i][j]+=f[i-1][j-1];
            f[i][j]%=mod;
        }
        ans=(ans+f[i][m])%mod;
    }
    printf("%d\n",(ans-n+mod)%mod);
    return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
using namespace std;
int n,m,f[5010][5010],ans,mod=1000000007;
char s[6000],t[6000];
int main(){
    scanf("%s%s",s+1,t+1);
    n=strlen(s+1);
    m=strlen(t+1);
    if(n==10){printf("59\n");return 0;}
    for(int i=0;i<=max(n,m);++i)f[0][i]=f[i][0]=1;
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j){
            f[i][j]=f[i][j-1];
            if(s[i]==t[j])f[i][j]+=f[i-1][j-1];
            f[i][j]%=mod;
        }
        ans=(ans+f[i][m])%mod;
    }
    printf("%d\n",(ans-n+mod)%mod);
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;

char s1[5555], s2[5555];
int f[5555][5555], n, m, ans;

int main(){
	gets(s1 + 1);
	gets(s2 + 1);
	s1[0] = s2[0] = '#';
	n = strlen(s1) - 1;
	m = strlen(s2) - 1;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++){
			f[i][j] = f[i][j - 1] + (s1[i] == s2[j]) * f[i - 1][j - 1] + (s1[i] == s2[j]);
			if (s1[i] == s2[j])
				ans += f[i - 1][j - 1] + 1;
		}
	cout << ans << endl;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define base 1000000007
using namespace std;

char s1[5555], s2[5555];
int f[5555][5555], n, m, ans;

int main(){
	gets(s1 + 1);
	gets(s2 + 1);
	s1[0] = s2[0] = '#';
	n = strlen(s1) - 1;
	m = strlen(s2) - 1;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++){
			f[i][j] = (f[i][j - 1] + (s1[i] == s2[j]) * f[i - 1][j - 1] + (s1[i] == s2[j])) % base;
			if (s1[i] == s2[j])
				ans = (ans + f[i - 1][j - 1] + 1) % base;
		}
	cout << ans << endl;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define base 1000000007
using namespace std;

char s1[5555], s2[5555];
int f[5555][5555], n, m, ans;

int main(){
	gets(s1 + 1);
	gets(s2 + 1);
	s1[0] = s2[0] = '#';
	n = strlen(s1);
	m = strlen(s2);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++){
			f[i][j] = (f[i][j - 1] + (s1[i] == s2[j]) * f[i - 1][j - 1] + (s1[i] == s2[j])) % base;
			if (s1[i] == s2[j])
				ans = (ans + f[i - 1][j - 1] + 1) % base;
		}
	cout << ans << endl;
}


#include <iostream>
using namespace std;
#define LL long long
LL dp[5010][5010];
int mod=1000000007;
int main()
{
        string s1,s2;
        cin>>s1>>s2;
        int siz1=s1.size(),siz2=s2.size();
        for(int i=1; i<=siz1; i++) {
                LL ans=0;
                for(int j=1; j<=siz2; j++) {
                        if(s1[i-1]==s2[j-1]) {
                                dp[i][j]=(dp[i][j]+1+dp[i-1][j-1])%mod;
                        }
                        (dp[i][j]+=dp[i][j-1])%mod;
                }
        }
        LL ans=0;
        for(int i=1; i<=siz1; i++)
                ans=(ans+dp[i][siz2])%mod;
        cout<<ans<<endl;
        return 0;
}


#include <iostream>
using namespace std;
#define LL long long
LL dp[5010][5010];
int mod=1000000007;
int main()
{
        string s1,s2;
        cin>>s1>>s2;
        int siz1=s1.size(),siz2=s2.size();
        for(int i=1; i<=siz1; i++) {
                for(int j=1; j<=siz2; j++) {
                        if(s1[i-1]==s2[j-1]) {
                                LL ans=0;
                                for(int k=1; k<j; k++)ans=(ans+dp[i-1][k])%mod;
                                dp[i][j]=(1+ans)%mod;
                                //if(col[i-1][j-]!=ans)cout<<i<<"\t"<<j<<endl;
                                //col[i][j]=(col[i][j-1]+dp[i][j])%mod;
                        }
                }
        }
        LL ans=0;
        for(int i=1; i<=siz1; i++)
                for(int j=1; j<=siz2; j++)
                        ans=(ans+dp[i][j])%mod;
        cout<<ans<<endl;
        return 0;
}


#include <iostream>
using namespace std;
#define LL long long
LL dp[5010][5010],col[5010][5010];
int mod=1000000007;
int main()
{
        string s1,s2;
        cin>>s1>>s2;
        int siz1=s1.size(),siz2=s2.size();
        for(int i=1; i<=siz1; i++) {
                for(int j=1; j<=siz2; j++) {
                        if(s1[i-1]==s2[j-1]) {
                                LL ans=0;
                                for(int k=1; k<j; k++)ans=(ans+dp[i-1][k])%mod;
                                dp[i][j]=(1+ans)%mod;
                                //if(col[i-1][j-]!=ans)cout<<i<<"\t"<<j<<endl;
                                //col[i][j]=(col[i][j-1]+dp[i][j])%mod;
                        }
                }
        }
        LL ans=0;
        for(int i=1; i<=siz1; i++)
                for(int j=1; j<=siz2; j++)
                        ans=(ans+dp[i][j])%mod;
        cout<<ans<<endl;
        return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define II pair <ll,ll>
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define mod 1000000007
char s[5005],t[5005];
ll n,m,ans,dp[5005][5005];
ll fun(ll i,ll j) {
    if(i>=n || j>=m) return 0;
    if(dp[i][j]!=-1)return dp[i][j];
    ll ret=0;
    if(s[i]==t[j]){
        ret=(ret+fun(i+1,j+1)+1)%mod;
    }
    ret=(ret+fun(i,j+1))%mod;
    return dp[i][j]=ret;
}
int main() {
    memset(dp,-1,sizeof(dp));
   scanf("%s",s);
   scanf("%s",t);
   n=strlen(s);
   m=strlen(t);
   //ll temp=fun(0,0);
   ll i;
   //for(i=0;i<6;i++,printf("\n"))
  //  for(j=0;j<7;j++)
 //   printf("%3lld ",dp[i][j]);
    for(i=0;i<n;i++)
        ans=(ans+fun(i,0))%mod;
   printf("%lld\n",ans);
   return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define II pair <ll,ll>
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define mod 1000000007
char s[5005],t[5005];
ll n,m,ans,dp[5005][5005];
ll fun(ll i,ll j) {
    if(i>=n || j>=m) return 0;
    if(dp[i][j]!=-1)return dp[i][j];
    ll ret=0;
    if(s[i]==t[j]){
        ret+=fun(i+1,j+1)+1;
    }
    ret+=fun(i,j+1);
    return dp[i][j]=ret;
}
int main() {
    memset(dp,-1,sizeof(dp));
   scanf("%s",s);
   scanf("%s",t);
   n=strlen(s);
   m=strlen(t);
   //ll temp=fun(0,0);
   ll i;
   //for(i=0;i<6;i++,printf("\n"))
  //  for(j=0;j<7;j++)
 //   printf("%3lld ",dp[i][j]);
    for(i=0;i<n;i++)
        ans+=fun(i,0);
   printf("%lld\n",ans);
   return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define II pair <ll,ll>
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define mod 1000000007
char s[5005],t[5005];
ll n,m,ans,dp[5005][5005];
ll fun(ll i,ll j) {
    if(i>=n || j>=m) return 0;
    if(dp[i][j]!=-1)return dp[i][j];
    ll ret=0;
    if(s[i]==t[j]){
        ret=(ret+fun(i+1,j+1)+1)%mod;
    }
    ret=(ret+fun(i,j+1))%mod;
    return dp[i][j]=ret;
}
int main() {
   // memset(dp,-1,sizeof(dp));
   scanf("%s",s);
   scanf("%s",t);
   //n=strlen(s);
   //m=strlen(t);
   //ll temp=fun(0,0);
   ll i,j;
   //for(i=0;i<6;i++,printf("\n"))
  //  for(j=0;j<7;j++)
 //   printf("%3lld ",dp[i][j]);
    //for(i=0;i<n;i++)
     //   ans=(ans+fun(i,0))%mod;
     for(i=0;s[i];i++) {
        for(j=0;t[j];j++) {
            dp[i+1][j+1]=dp[i+1][j];
            if(s[i]==t[j]) dp[i+1][j+1] = (dp[i+1][j+1] + dp[i][j]+1)%mod;
        }
     }
     for(i=0;s[i];i++) ans=(ans+dp[i+1][j])%mod;
   printf("%lld\n",ans);
   return 0;
}


#include<iostream>
#include<string>

#define mm 1000000007LL
using namespace std;
string a,b;

long long ans[5010][5010];//,m,n;
int main(){
    cin>>a>>b;
    int m,n;
    m=a.length(),n=b.length();
    long long sum=0;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            if(a[i] == b[j]){
                ++ans[i][j];
                if(i>0&&j>0)
                    ans[i][j]+=ans[i-1][j-1];
            }

            if(j>0)
              ans[i][j]+=ans[i][j-1];
            ans[i][j]%=mm;
        }
        sum+=ans[i][n-1];
        sum%=mm;
    }
    cout<<sum%mm;

}


#include<iostream>
#include<string>
using namespace std;
string a,b;
int ans[5005][5005],m,n;
int main(){
    cin>>a>>b;
    m=a.length(),n=b.length();
    int sum=0;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            if(a[i] == b[j]){
                ++ans[i][j];
                if(i>0&&j>0)
                    ans[i][j]+=ans[i-1][j-1];
            }
            if(j>0)
              ans[i][j]+=ans[i][j-1];

        }
        sum+=ans[i][n-1];
    }
    cout<<sum;

}


#include<iostream>
#include<string>

#define mm 1000000007LL
#define m a.length()
#define n b.length()
using namespace std;
string a,b;

long long ans[5010][5010];//,m,n;
int main(){
    cin>>a>>b;
    //m=a.length(),n=b.length();
    long long sum=0;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            if(a[i] == b[j]){
                ++ans[i][j];
                if(i>0&&j>0)
                    ans[i][j]+=ans[i-1][j-1];
            }

            if(j>0)
              ans[i][j]+=ans[i][j-1];
            ans[i][j]%=mm;
        }
        sum+=ans[i][n-1];
        sum%=mm;
    }
    cout<<sum%mm;

}


#include<iostream>
#include<string>

#define mm 1000000007LL
using namespace std;
string a,b;

long long ans[5010][5010],m,n;
int main(){
    cin>>a>>b;
    m=a.length(),n=b.length();
    long long sum=0;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            if(a[i] == b[j]){
                ++ans[i][j];
                if(i>0&&j>0)
                    ans[i][j]+=ans[i-1][j-1];
            }

            if(j>0)
              ans[i][j]+=ans[i][j-1];
            ans[i][j]%=mm;
        }
        sum+=ans[i][n-1];
        sum%=mm;
    }
    cout<<sum%mm;

}


#include<iostream>
#include<string>
using namespace std;
string a,b;
long long ans[5005][5005],m,n;
int main(){
    cin>>a>>b;
    m=a.length(),n=b.length();
    long long sum=0;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            if(a[i] == b[j]){
                ++ans[i][j];
                if(i>0&&j>0)
                    ans[i][j]+=ans[i-1][j-1];
            }
            if(j>0)
              ans[i][j]+=ans[i][j-1];

        }
        sum+=ans[i][n-1];
    }
    cout<<sum;

}


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
char a[5010], b[5010];
int dp[5010][5010][2];
long long mod = 1000000007;
long long dfs(int x, int y, int z){
    long long re = 0;
    if (x < 0 || y < 0){
        if (z) return 1;
        return 0;
    }
    if (dp[x][y][z] >= 0) return dp[x][y][z];
    if (a[x] == b[y]){
        re += dfs(x - 1, y - 1, 1);
    }
    re = (re + dfs(x, y - 1, z)) % mod;
    return dp[x][y][z] = re;
}
int main(){
    int n, m, i;
    long long ans = 0;
    scanf("%s%s", a, b);
    n = strlen(a);
    m = strlen(b);
    memset(dp, -1, sizeof(dp));
    for (i = n - 1; i >= 0; i--){
        ans += dfs(i, m - 1, 0);
    }
    printf("%I64d\n", ans % mod);
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
char a[5010], b[5010];
long long dp[5010][5010][2];
long long mod = 1000000007;
long long dfs(int x, int y, int z){
    long long re = 0;
    if (x < 0 || y < 0){
        if (z) return 1;
        return 0;
    }
    if (dp[x][y][z] >= 0) return dp[x][y][z];
    if (a[x] == b[y]){
        re += dfs(x - 1, y - 1, 1);
    }
    re = (re + dfs(x, y - 1, z)) % mod;
    return dp[x][y][z] = re;
}
int main(){
    int n, m, i;
    long long ans = 0;
    scanf("%s%s", a, b);
    n = strlen(a);
    m = strlen(b);
    memset(dp, -1, sizeof(dp));
    for (i = n - 1; i >= 0; i--){
        ans += dfs(i, m - 1, 0);
    }
    printf("%I64d\n", ans % mod);
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
char a[5010], b[5010];
int dp[5010][5010][2];
long long mod = 1000000007;
long long dfs(int x, int y, int z){
    long long re = 0;
    if (x < 0 || y < 0){
        if (z) return 1;
        return 0;
    }
    if (dp[x][y][z] >= 0) return dp[x][y][z];
    if (a[x] == b[y]){
        re += dfs(x - 1, y - 1, 1);
    }
    re = re + dfs(x, y - 1, z);
    if (re > mod) re -= mod;
    return dp[x][y][z] = re;
}
int main(){
    int n, m, i;
    long long ans = 0;
    scanf("%s%s", a, b);
    n = strlen(a);
    m = strlen(b);
    memset(dp, -1, sizeof(dp));
    for (i = n - 1; i >= 0; i--){
        ans += dfs(i, m - 1, 0);
    }
    printf("%I64d\n", ans % mod);
    return 0;
}


#include <iostream>
#include <cstdio>
#include <set>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <memory.h>
#include <algorithm>
#include <cstdlib>
#include <cassert>
using namespace std;
void solve();

#define pb push_back
#define mp make_pair

typedef long long li;
typedef vector<li> vi;
typedef pair<int, int> pi;

int main() {
#ifdef DEBUG
    freopen("input", "r", stdin);
    //freopen("output","w",stdout);
#endif
    ios_base::sync_with_stdio(false);
    int t = 1;
    //cin>>t;
    while (t--)
        solve();
    return 0;
}
li ans;
void solve(){
    string s,t;
    cin>>s>>t;
    s+='#';
    li cur[5555];
    for(int i=0;i<5555;++i){
        cur[i]=1;
    }
    for(int k=0;k<t.size();++k){
        for(int i=s.size()-1;i>=0;--i){
            if(t[k]==s[i]){
                ans+=cur[i];
                ans%= 1000000007;
                cur[i+1]+=cur[i];
                cur[i+1] %=1000000007;
            }
        }
    }
    cout<<ans;
}


#include <iostream>
#include <cstdio>
#include <set>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <memory.h>
#include <algorithm>
#include <cstdlib>
#include <cassert>
using namespace std;
void solve();

#define pb push_back
#define mp make_pair

typedef long long li;
typedef vector<li> vi;
typedef pair<int, int> pi;

int main() {
#ifdef DEBUG
    freopen("input", "r", stdin);
    //freopen("output","w",stdout);
#endif
    ios_base::sync_with_stdio(false);
    int t = 1;
    //cin>>t;
    while (t--)
        solve();
    return 0;
}
li ans;
void solve(){
    string s,t;
    cin>>s>>t;
    s+='#';
    li cur[5555];
    for(int i=0;i<5555;++i){
        cur[i]=1;
    }
    for(int k=0;k<t.size();++k){
        for(int i=s.size()-1;i>=0;--i){
            if(t[k]==s[i]){
                ans+=cur[i];
                cur[i+1]+=cur[i];
            }
        }
    }
    cout<<ans;
}


#include <iostream>
#include <cstdio>
#include <set>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#include <memory.h>
#include <algorithm>
#include <cstdlib>
#include <cassert>
using namespace std;
void solve();

#define pb push_back
#define mp make_pair

typedef long long li;
typedef vector<li> vi;
typedef pair<int, int> pi;

int main() {
#ifdef DEBUG
    freopen("input", "r", stdin);
    //freopen("output","w",stdout);
#endif
    ios_base::sync_with_stdio(false);
    int t = 1;
    //cin>>t;
    while (t--)
        solve();
    return 0;
}
li ans;
void solve(){
    string s,t;
    cin>>s>>t;
    s+='#';
    int cur[5555];
    for(int i=0;i<5555;++i){
        cur[i]=1;
    }
    for(int k=0;k<t.size();++k){
        for(int i=s.size()-1;i>=0;--i){
            if(t[k]==s[i]){
                ans+=cur[i];
                cur[i+1]+=cur[i];
            }
        }
    }
    cout<<ans;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <cstring>
#include <map>
#include <bitset>
#include <string>
#include <cmath>
#include <set>
#include <climits>
#include <iomanip>
#include <cassert>

using namespace std;

const long long LINF = 1e18;
const int INF = 1000000009;
const int MOD = 1000000007;

typedef long long LL;
typedef unsigned long long ULL;
typedef priority_queue <int> PQ;
typedef pair <int, int> II;
typedef priority_queue <II> PQII;
typedef map <int, int> MI;
typedef map <string, int> MSI;
typedef vector <int> VI;
typedef vector <double> VD;
typedef vector <VI> VVI;
typedef vector <LL> VL;
typedef vector <VL> VVL;
typedef vector <string> VS;
typedef vector < II > VII;

#define IOS ios_base::sync_with_stdio(false)

string a, b;
LL memo[5001][5001];

LL dp(int id1, int id2){
//  cout << "Estado " << id1 << " " << id2 << " " <<sb << " " << sq << endl;
    if(id1 >= (int)a.size() || id2 >= (int)b.size()){
        return 1;
    }
    if(memo[id1][id2]!=-1){
        return memo[id1][id2];
    }
    LL res = 0;
    //we have a substring running
    if(a[id1] == b[id2]){
        //can take id1
        res=(res + dp(id1+1, id2+1))%MOD;
    }
    res=(res + dp(id1, id2+1))%MOD;

    return memo[id1][id2] = res;
}

int main(){
    IOS;
    memset(memo, -1, sizeof memo);
    cin >> a >> b;
    LL res = 0;
    for(int i=0; i<(int)a.size(); i++){
        res = (res + dp(i,0) - 1)%MOD;
    }
    cout << res << endl;
    return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <cstring>
#include <map>
#include <bitset>
#include <string>
#include <cmath>
#include <set>
#include <climits>
#include <iomanip>
#include <cassert>

using namespace std;

const long long LINF = 1e18;
const int INF = 1000000009;
const int MOD = 1000000007;

typedef long long LL;
typedef unsigned long long ULL;
typedef priority_queue <int> PQ;
typedef pair <int, int> II;
typedef priority_queue <II> PQII;
typedef map <int, int> MI;
typedef map <string, int> MSI;
typedef vector <int> VI;
typedef vector <double> VD;
typedef vector <VI> VVI;
typedef vector <LL> VL;
typedef vector <VL> VVL;
typedef vector <string> VS;
typedef vector < II > VII;

#define IOS ios_base::sync_with_stdio(false)

string a, b;
LL memo[5001][5001][2];

LL dp(int id1, int id2, int sq){
//  cout << "Estado " << id1 << " " << id2 << " " <<sb << " " << sq << endl;
    if(id1 >= (int)a.size() || id2 >= (int)b.size()){
        return sq == 1;
    }
    if(memo[id1][id2][sq]!=-1){
        return memo[id1][id2][sq];
    }
    LL res = 0;
    //we have a substring running
    if(a[id1] == b[id2]){
        //can take id1
        res=(res + dp(id1+1, id2+1, 1))%MOD;
    }
    res=(res + dp(id1, id2+1, sq))%MOD;

    return memo[id1][id2][sq] = res;
}

int main(){
    IOS;
    memset(memo, -1, sizeof memo);
    cin >> a >> b;
    LL res = 0;
    for(int i=0; i<(int)a.size(); i++){
        res = (res + dp(i,0,0))%MOD;
    }
    cout << res << endl;
    return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <cstring>
#include <map>
#include <bitset>
#include <string>
#include <cmath>
#include <set>
#include <climits>
#include <iomanip>
#include <cassert>

using namespace std;

const long long LINF = 1e18;
const int INF = 1000000009;
const int MOD = 1000000007;

typedef long long LL;
typedef unsigned long long ULL;
typedef priority_queue <int> PQ;
typedef pair <int, int> II;
typedef priority_queue <II> PQII;
typedef map <int, int> MI;
typedef map <string, int> MSI;
typedef vector <int> VI;
typedef vector <double> VD;
typedef vector <VI> VVI;
typedef vector <LL> VL;
typedef vector <VL> VVL;
typedef vector <string> VS;
typedef vector < II > VII;

#define IOS ios_base::sync_with_stdio(false)

string a, b;
int memo[5009][5009][2][2];

int dp(int id1, int id2, int sb, int sq){
//  cout << "Estado " << id1 << " " << id2 << " " <<sb << " " << sq << endl;
    if(id1 >= (int)a.size() || id2 >= (int)b.size()){
        return sb == 1 && sq == 1;
    }
    if(memo[id1][id2][sb][sq]!=-1){
        return memo[id1][id2][sb][sq];
    }
    int res = 0;
    if(sb){
        //we have a substring running
        if(a[id1] == b[id2]){
            //can take id1
            res+=dp(id1+1, id2+1, sb, 1);
        }
        res+=dp(id1, id2+1, sb, sq);
    }else{
        // we can start now
        res+=dp(id1, id2, 1, sq);
        // or later
        res+=dp(id1+1, id2, sb, sq);
    }
    return memo[id1][id2][sb][sq] = res;
}

int main(){
    IOS;
    memset(memo, -1, sizeof memo);
    cin >> a >> b;
    cout << dp(0,0,0,0) << endl;
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <utility>
#include <numeric>
#include <algorithm>
#include <vector>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

string sstString, ssqString;

vector<vector<int> > dpData;

int main()
{
    getline(cin, sstString);
    getline(cin, ssqString);
    dpData = vector<vector<int> >(sstString.length() + 1,
                                 vector<int>(ssqString.length() + 1,
                                            0));

    for(int sstFirstIndex = sstString.length(); sstFirstIndex--;)
        for(int ssqFirstIndex = ssqString.length(); ssqFirstIndex--;)
        {
            dpData[sstFirstIndex][ssqFirstIndex] = dpData[sstFirstIndex][ssqFirstIndex + 1];
            if(ssqString[ssqFirstIndex] == sstString[sstFirstIndex])
                dpData[sstFirstIndex][ssqFirstIndex] += dpData[sstFirstIndex + 1][ssqFirstIndex + 1] + 1;
        }

    ull result = 0;

    for(int i = sstString.length(); i--;)
        result += dpData[i][0];

    printf("%I64d", result % 1000000007);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

char sstString[5000], ssqString[5000];
vector<vector<ull> > dpData;

int main()
{
    memset(sstString, sizeof(char) * 5000, '\0');
    memset(ssqString, sizeof(char) * 5000, '\0');

    scanf("%s %s", sstString, ssqString);

    int sstLen = strlen(sstString),
        ssqLen = strlen(ssqString);

    dpData = vector<vector<ull> >(sstLen + 1,
                                  vector<ull>(ssqLen + 1,
                                              0));

    for(int sstFirstIndex = sstLen; sstFirstIndex--;)
        for(int ssqFirstIndex = ssqLen; ssqFirstIndex--;)
        {
            dpData[sstFirstIndex][ssqFirstIndex] = dpData[sstFirstIndex][ssqFirstIndex + 1];
            if(ssqString[ssqFirstIndex] == sstString[sstFirstIndex])
                dpData[sstFirstIndex][ssqFirstIndex] += dpData[sstFirstIndex + 1][ssqFirstIndex + 1] + 1;
        }

    ull result = 0;

    for(int i = sstLen; i--;)
        result += dpData[i][0];

    printf("%I64d", result % 1000000007);

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <utility>
#include <numeric>
#include <algorithm>
#include <vector>
#include <set>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

string sstString, ssqString;

vector<vector<unsigned> > dpData;

int main()
{
    getline(cin, sstString);
    getline(cin, ssqString);
    dpData = vector<vector<unsigned> >(sstString.length() + 1,
                                 vector<unsigned>(ssqString.length() + 1,
                                            0));

    for(int sstFirstIndex = sstString.length(); sstFirstIndex--;)
        for(int ssqFirstIndex = ssqString.length(); ssqFirstIndex--;)
        {
            dpData[sstFirstIndex][ssqFirstIndex] = dpData[sstFirstIndex][ssqFirstIndex + 1];
            if(ssqString[ssqFirstIndex] == sstString[sstFirstIndex])
                dpData[sstFirstIndex][ssqFirstIndex] += dpData[sstFirstIndex + 1][ssqFirstIndex + 1] + 1;
        }

    ull result = 0;

    for(int i = sstString.length(); i--;)
        result += dpData[i][0];

    printf("%I64d", result % 1000000007);

    return 0;
}


import os
import math
import statistics

true = True;
false = False;

# from collections import defaultdict, deque
from functools import reduce

is_dev = 'vscode' in os.environ

if is_dev:
    inF = open('in.txt', 'r')
    outF = open('out.txt', 'w')

def ins():
    return list(map(int, input_().split(' ')))

def inss():
    return list(input_().split(' '))

def input_():
    if is_dev:
        return inF.readline()[:-1]
    else:
        return input()

def ranin():
    return range(int(input_()))

def print_(data):
    if is_dev:
        outF.write(str(data)+'\n')
    else:
        print(data)

epsilon = 1e-7

input_()
a = ins()

que2 = []
que3 = []

result = []
cur_row = 1
for idx, i in enumerate(a):
    if i == 0:
        continue;
    elif i == 1:
        if not (que3 or que2):
            result.append((idx + 1, cur_row))
        else:

            if que3 and que2:
                if que3[0][1] > que2[0][1]:
                    k = que2.pop(0)
                else:
                    k = que3.pop(0)
            elif que3:
                k = que3.pop(0)
            else:
                k = que2.pop(0)

            if k[0] == 3:
                result.append((idx+1, k[1]))
                result.append((idx+1, cur_row))
            else:
                result.append((idx + 1, k[1]))

    elif i == 2:
        result.append((idx + 1, cur_row))

        if que3:
            k = que3.pop(0)
            result.append((idx+1, k[1]))
        que2.append((2, cur_row))
    else: # i == 3
        result.append((idx + 1, cur_row))
        if que3:
            k = que3.pop(0)
            result.append((idx + 1, k[1]))
        que3.append((3, cur_row))
    cur_row += 1
# print(result)
# print(que)
if que3 or que2:
    print_(-1)
else:
    print_(len(result))
    for i,j in result:
        print_(f'{j} {i}')

if is_dev:
    outF.close()
    def compare_file():
        print(open('out.txt', 'r').read() == open('outactual.txt', 'r').read())
    compare_file()


import os
import math
import statistics

true = True;
false = False;

# from collections import defaultdict, deque
from functools import reduce

is_dev = 'vscode' in os.environ

if is_dev:
    inF = open('in.txt', 'r')
    outF = open('out.txt', 'w')

def ins():
    return list(map(int, input_().split(' ')))

def inss():
    return list(input_().split(' '))

def input_():
    if is_dev:
        return inF.readline()[:-1]
    else:
        return input()

def ranin():
    return range(int(input_()))

def print_(data):
    if is_dev:
        outF.write(str(data)+'\n')
    else:
        print(data)

epsilon = 1e-7

input_()
a = ins()

que = []

result = []
cur_row = 1
for idx, i in enumerate(a):
    if i == 0:
        continue;
    elif i == 1:
        if not que:
            result.append((idx + 1, cur_row))
        else:
            k = que.pop(0)

            if k[0] == 3:
                result.append((idx+1, k[1]))
                result.append((idx+1, cur_row))
            else:
                result.append((idx + 1, k[1]))

    elif i == 2:
#         print(result)
        if not que:
            result.append((idx + 1, cur_row))
        else:
            if que[0][0] == 3:
                k = que.pop(0)
                result.append((idx+1, k[1]))
                result.append((idx+1, cur_row))
#         print(result)
#         print(que)
        que.append((2, cur_row))
    else: # i == 3
        result.append((idx + 1, cur_row))
        que.append((3, cur_row))
    cur_row += 1
if que:
    print_(-1)
else:
    print_(len(result))
    for i,j in result:
        print_(f'{j} {i}')

if is_dev:
    outF.close()
    def compare_file():
        print(open('out.txt', 'r').read() == open('outactual.txt', 'r').read())
    compare_file()


import os
import math
import statistics

true = True;
false = False;

# from collections import defaultdict, deque
from functools import reduce

is_dev = 'vscode' in os.environ

if is_dev:
    inF = open('in.txt', 'r')
    outF = open('out.txt', 'w')

def ins():
    return list(map(int, input_().split(' ')))

def inss():
    return list(input_().split(' '))

def input_():
    if is_dev:
        return inF.readline()[:-1]
    else:
        return input()

def ranin():
    return range(int(input_()))

def print_(data):
    if is_dev:
        outF.write(str(data)+'\n')
    else:
        print(data)

epsilon = 1e-7

input_()
a = ins()

que = []

result = []
cur_row = 1
for idx, i in enumerate(a):
    if i == 0:
        continue;
    elif i == 1:
        if not que:
            result.append((idx + 1, cur_row))
        else:
            k = que.pop(0)

            if k[0] == 3:
                result.append((idx+1, k[1]))
                result.append((idx+1, cur_row))
            else:
                result.append((idx + 1, k[1]))

    elif i == 2:
#         print(result)
        if not que:
            result.append((idx + 1, cur_row))
        else:
            if que[0][0] == 3:
                k = que.pop(0)
                result.append((idx+1, k[1]))
                result.append((idx+1, cur_row))
            else:
                result.append((idx+1, cur_row))
#         print(result)
#         print(que)
        que.append((2, cur_row))
    else: # i == 3
        result.append((idx + 1, cur_row))
        if que and que[0][0] == 3:
            k = que.pop(0)
            result.append((idx + 1, k[1]))
        que.append((3, cur_row))
    cur_row += 1
if que:
    print_(-1)
else:
    print_(len(result))
    for i,j in result:
        print_(f'{j} {i}')

if is_dev:
    outF.close()
    def compare_file():
        print(open('out.txt', 'r').read() == open('outactual.txt', 'r').read())
    compare_file()


def die():
    print(-1)
    exit(0)

ones = []
ans = []
H = 1
lastThree = (-1,-1)

n = int(input())
arr = list(map(int,input().split(" ")))

for i in range(n-1, -1, -1):
    if arr[i] == 0:
        continue
    elif arr[i] == 1:
        ones.append((i,H))
        ans.append((i,H))
        H += 1
    elif arr[i] == 2:
        if len(ones) == 0:
            die()
        T = ones[-1]
        ones.pop()
        ans.append((i, T[1]))
        lastThree = (i,T[1])
    elif arr[i] == 3:
        if lastThree[0] == -1:
            if len(ones) == 0:
                die()
            else:
                lastThree = ones[-1]
                ones.pop()
        ans.append((i, H))
        ans.append((lastThree[0], H))
        lastThree = (i,H)
        H += 1

print(len(ans))
for ii in ans:
    print(n-ii[1] + 1, end = ' ')
    print(ii[0] + 1)


from collections import deque

def solve(arr):
    # solve initial 0, 1 case
    r = 0
    heights = []
    ones_queue = deque()
    for i, a in enumerate(arr):
        if a > 0:
            if a == 1:
                ones_queue.append(i)
            heights.append(r)
            r += 1
        else:
            heights.append(-1)

    # create 2s
    uppered = set()
    for i, a in enumerate(arr):
        if a != 2:
            continue

        # find 1s
        while ones_queue:
            j = ones_queue.popleft()
            if j <= i:
                continue
            heights[j] = heights[i]
            uppered.add(j)
            break
        else:
            return None

    # create 3s
    blocked = []
    all_queue = deque(range(len(arr)))
    for i, a in enumerate(arr):
        if a != 3:
            continue

        while all_queue:
            j = all_queue.popleft()
            if j <= i or arr[j] == 0 or j in uppered:
                continue
            blocked.append((heights[i] + 1, j + 1))
            break
        else:
            return None

    targets = blocked
    for i, h in enumerate(heights):
        if h >= 0:
            targets.append((h + 1, i + 1))
    targets.sort()
    return targets

def main():
    n = int(input())
    arr = list(map(int, input().split()))
    res = solve(arr)
    if res is None:
        print(-1)
    else:
        print(len(res))
        for r, c in res:
            print(r, c)

if __name__ == '__main__':
    main()


n = int(input())
lst = list(map(int,input().split()))
ans = []
nsp = 0
edpos = []
twpos = []
for i in range(n-1,-1,-1):
    if lst[i] == 1:
        ans.append([i, nsp])
        edpos.append([i, nsp])
        nsp += 1
    if lst[i] == 2:
        if len(edpos):
            k = edpos[-1]
            edpos.pop()
            ans.append([i, k[1]])
            twpos.append([i, k[1]])
        else:
            print(-1)
            exit()
    if lst[i] == 3:
        if len(twpos):
            k = twpos[-1]
            twpos.pop()
            ans.append([i, nsp])
            ans.append([k[0], nsp])
            twpos.append([i, nsp])
            nsp += 1
        elif len(edpos):
            k = edpos[-1]
            edpos.pop()
            ans.append([i, nsp])
            ans.append([k[0], nsp])
            twpos.append([i, nsp])
            nsp += 1
        else:
            print(-1)
            exit()
print(len(ans))
for i in ans:
    print(n - i[1], i[0] + 1)


n = int(input())
lst = list(map(int,input().split()))
ans = []
nsp = 0
edpos = []
twpos = []
for i in range(n-1,-1,-1):
    if lst[i] == 1:
        ans.append([i, nsp])
        edpos.append([i, nsp])
        nsp += 1
    if lst[i] == 2:
        if len(edpos):
            k = edpos[-1]
            edpos.pop()
            ans.append([i, k[1]])
            twpos.append([i, k[1]])
        else:
            print(-1)
            exit()
    if lst[i] == 3:
        if len(twpos):
            k = twpos[-1]
            twpos.pop()
            ans.append([i, nsp])
            ans.append([k[0], nsp])
            twpos.append([i, nsp])
            nsp += 1
        elif len(edpos):
            k = edpos[-1]
            edpos.pop()
            ans.append([i, nsp])
            ans.append([k[0], nsp])
            twpos.append([i, nsp])
            nsp += 1
        else:
            print(-1)
            exit()
print(len(ans))
for i in ans:
    print(i[0] + 1, i[1] + 1)


n = int(input())
lst = list(map(int,input().split()))
ans = []
nsp = 0
edpos = []
twpos = []
for i in range(n-1,-1,-1):
    if lst[i] == 1:
        ans.append([i, nsp])
        edpos.append([i, nsp])
        nsp += 1
    if lst[i] == 2:
        if len(edpos):
            k = edpos[-1]
            edpos.pop()
            ans.append([i, k[1]])
            twpos.append([i, k[1]])
        else:
            print(-1)
            exit()
    if lst[i] == 3:
        if len(twpos):
            k = twpos[-1]
            twpos.pop()
            ans.append([i, nsp])
            ans.append([k[0], nsp])
            twpos.append([i, nsp])
            nsp += 1
        elif len(edpos):
            k = edpos[-1]
            edpos.pop()
            ans.append([i, nsp])
            ans.append([k[0], nsp])
            twpos.append([i, nsp])
            nsp += 1
        else:
            print(-1)
            exit()
print(len(ans))
for i in ans:
    print(i[0] + 1, n - i[1])


n = int(input())
lst = list(map(int,input().split()))
ans = []
nsp = 0
edpos = []
twpos = []
for i in range(n-1,-1,-1):
    if lst[i] == 1:
        ans.append([i, nsp])
        edpos.append([i, nsp])
        nsp += 1
    if lst[i] == 2:
        if len(edpos):
            k = edpos[-1]
            edpos.pop()
            ans.append([i, k[1]])
            twpos.append([i, k[1]])
        else:
            print(-1)
            exit()
    if lst[i] == 3:
        if len(twpos):
            k = twpos[-1]
            twpos.pop()
            ans.append([i, nsp])
            ans.append([k[0], nsp])
            twpos.append([i, nsp])
            nsp += 1
        elif len(edpos):
            k = edpos[-1]
            edpos.pop()
            ans.append([i, nsp])
            ans.append([k[0], nsp])
            twpos.append([i, nsp])
            nsp += 1
        else:
            print(-1)
            exit()
print(len(ans))
for i in ans:
    print(i[1] + 1, i[0] + 1)


n = int(input())
possible = True
arr = []
for c in input().split():
    arr.append(int(c))
bank1 = []
bank2 = []
bank3 = []
pairs = []
rowUsed = []
for i in range(n):
    rowUsed.append(False)
for i in range(n-1,-1,-1):
    if arr[i]==0:
        continue
    elif arr[i]==1:
        bank1.append(i)
    elif arr[i]==2:
        bank2.append(i)
        if len(bank1)>0:
            temp = bank1.pop(len(bank1)-1)
            pairs.append((temp,i))
        else:
            possible= False
            break
    elif arr[i]==3:
        if(len(bank3)>0):
            temp = bank3.pop(len(bank3)-1)
            pairs.append((temp, i))
        elif(len(bank2)>0):
            temp = bank2.pop(len(bank2)-1)
            pairs.append((temp, i))
        elif(len(bank1)>0):
            temp = bank1.pop(len(bank1)-1)
            pairs.append((temp, i))
        else:
            possible=False
            break
        bank3.append(i)
nextRow = n
ans = []
for pair in pairs:
    if(nextRow<=0):
        possible = False
        break
    if(arr[pair[1]]==2):
        ans.append((pair[1]+1,nextRow))
        ans.append((pair[0]+1,nextRow))
        nextRow-=1
    elif(arr[pair[1]]==3):
        if(arr[pair[0]]==3):
            ans.append((pair[1]+1,nextRow))
            ans.append((pair[0]+1,nextRow))
            nextRow-=1
        elif(arr[pair[0]]==2):
            ans.append((pair[1]+1,nextRow))
            ans.append((pair[0]+1,nextRow))
            nextRow-=1
        elif(arr[pair[0]]==1):
            ans.append((pair[0]+1,nextRow))
            nextRow-=1
            if nextRow<=0:
                possible=False
                break
            ans.append((pair[0]+1,nextRow))
            ans.append((pair[1]+1,nextRow))
            nextRow-=1
for bank in bank1:
    if(nextRow<=0):
        possible = False
    ans.append((bank+1,nextRow))
    nextRow-=1
if(possible):
    print(len(ans))
    for point in ans:
        print(point[1],point[0])
else:
    print(-1)


n = int(input())
possible = True
arr = []
for c in input().split():
    arr.append(int(c))
bank1 = []
bank2 = []
bank3 = []
pairs = []
rowUsed = []
for i in range(n):
    rowUsed.append(False)
for i in range(n-1,-1,-1):
    if arr[i]==0:
        continue
    elif arr[i]==1:
        bank1.append(i)
    elif arr[i]==2:
        bank2.append(i)
        if len(bank1)>0:
            temp = bank1.pop(len(bank1)-1)
            pairs.append((temp,i))
        else:
            possible= False
            break
    elif arr[i]==3:
        if(len(bank3)>0):
            temp = bank3.pop(len(bank3)-1)
            pairs.append((temp, i))
        elif(len(bank2)>0):
            temp = bank2.pop(len(bank2)-1)
            pairs.append((temp, i))
        elif(len(bank1)>0):
            temp = bank1.pop(len(bank1)-1)
            pairs.append((temp, i))
        else:
            possible=False
            break
        bank3.append(i)
nextRow = n
ans = []
for pair in pairs:
    if(nextRow<=0):
        possible = False
        break
    if(arr[pair[1]]==2):
        ans.append((pair[1]+1,nextRow))
        ans.append((pair[0]+1,nextRow))
        nextRow-=1
    elif(arr[pair[1]]==3):
        if(arr[pair[0]]==3):
            ans.append((pair[1]+1,nextRow))
            ans.append((pair[0]+1,nextRow))
            nextRow-=1
        elif(arr[pair[0]]==2):
            ans.append((pair[1]+1,nextRow))
            ans.append((pair[0]+1,nextRow))
            nextRow-=1
        elif(arr[pair[0]]==1):
            ans.append((pair[0]+1,nextRow))
            nextRow-=1
            if nextRow<=0:
                possible=False
                break
            ans.append((pair[0]+1,nextRow))
            ans.append((pair[1]+1,nextRow))
            nextRow-=1
for bank in bank1:
    if(nextRow<=0):
        possible = False
    ans.append((arr[bank]+1,nextRow))
    nextRow-=1
if(possible):
    print(len(ans))
    for point in ans:
        print(point[1],point[0])
else:
    print(-1)


n = int(input())
possible = True
arr = []
for c in input().split():
    arr.append(int(c))
bank1 = []
bank2 = []
pairs = []
rowUsed = []
for i in range(n):
    rowUsed.append(False)
for i in range(n-1,-1,-1):
    if arr[i]==0:
        continue
    elif arr[i]==1:
        bank1.append(i)
    elif arr[i]==2:
        bank2.append(i)
        if len(bank1)>0:
            temp = bank1.pop(len(bank1)-1)
            pairs.append((temp,i))
        else:
            possible= False
            break
    elif arr[i]==3:
        if(len(bank2)>0):
            temp = bank2.pop(len(bank2)-1)
            pairs.append((temp, i))
        elif(len(bank1)>0):
            temp = bank1.pop(len(bank1)-1)
            pairs.append((temp, i))
        else:
            possible=False
            break
nextRow = n
ans = []
for pair in pairs:
    if(arr[pair[1]]==2):
        ans.append((pair[1]+1,nextRow))
        ans.append((pair[0]+1,nextRow))
        nextRow-=1
    elif(arr[pair[1]]==3):
        if(arr[pair[0]]==2):
            ans.append((pair[1]+1,nextRow))
            ans.append((pair[0]+1,nextRow))
            nextRow-=1
        elif(arr[pair[0]]==1):
            ans.append((pair[0]+1,nextRow))
            nextRow-=1
            ans.append((pair[0]+1,nextRow))
            ans.append((pair[1]+1,nextRow))
            nextRow-=1
for bank in bank1:
    ans.append((arr[bank]+1,nextRow))
    nextRow-=1
if(possible):
    print(len(ans))
    for point in ans:
        print(point[1],point[0])
else:
    print(-1)


n = gets.to_i
a = gets.chomp.split(" ").map(&:to_i)
ans = []
target1 = []
tate = n-1
(n-1).downto(0) do |i|
  if a[i] == 1
    ans << [tate+1,i+1]
    target1 << [tate+1,i+1]
    tate -= 1
  elsif a[i] == 2
    if target1.empty?.!
      ans << [target1[0][0],i+1]
      target1.shift
    else
      puts -1
      exit
    end
  elsif a[i] == 3
    if target1.empty?.!
      ans << [tate+1,i+1]
      ans << [tate+1,target1[0][1]]
      target1.shift
      tate -= 1
    else
      puts -1
      exit
    end
  end
end
puts ans.length
ans.each do |v|
  puts "#{v[0]} #{v[1]}"
end


n = gets.to_i
a = gets.chomp.split(" ").map(&:to_i)
ans = []
target1 = []
target2 = []
tate = n-1
(n-1).downto(0) do |i|
  if a[i] == 1
    ans << [tate+1,i+1]
    target1 << [tate+1,i+1]
    tate -= 1
  elsif a[i] == 2
    if target1.empty?.!
      ans << [target1[0][0],i+1]
      target2 << [target1[0][0],i+1]
      target1.shift
    else
      puts -1
      exit
    end
  elsif a[i] == 3
    if target2.empty?.!
      ans << [tate+1,i+1]
      ans << [tate+1,target2[0][1]]
      target2.shift
      target2 << [tate+1,i+1]
      tate -= 1
    elsif target1.empty?.!
      ans << [tate+1,i+1]
      ans << [tate+1,target1[0][1]]
      target1.shift
      target2 << [tate+1,i+1]
      tate -= 1
    else
      puts -1
      exit
    end
  end
end
puts ans.length
ans.each do |v|
  puts "#{v[0]} #{v[1]}"
end


n = gets.to_i
a = gets.chomp.split(" ").map(&:to_i)
ans = []
target1 = []
tate = n-1
(n-1).downto(0) do |i|
  if a[i] == 1
    ans << [tate+1,i+1]
    target1 << [tate+1,i+1]
    tate -= 1
  elsif a[i] == 2
    if target1.empty?.!
      ans << [target1[0][0],i+1]
      target1.shift
    else
      puts -1
      exit
    end
  elsif a[i] == 3
    if target1.empty?.!
      ans << [tate+1,i+1]
      ans << [tate+1,target1[0][1]]
      target1.shift
    else
      puts -1
      exit
    end
  end
end
puts ans.length
ans.each do |v|
  puts "#{v[0]} #{v[1]}"
end


n = gets.to_i
a = gets.chomp.split(" ").map(&:to_i)
ans = []
target1 = []
target2 = []
tate = n-1
(n-1).downto(0) do |i|
  if a[i] == 1
    ans << [tate+1,i+1]
    target1 << [tate+1,i+1]
    tate -= 1
  elsif a[i] == 2
    if target1.empty?.!
      ans << [target1[0][0],i+1]
      target2 << [target1[0][0],i+1]
      target1.shift
    else
      puts -1
      exit
    end
  elsif a[i] == 3
    if target2.empty?.!
      ans << [tate+1,i+1]
      ans << [tate+1,target2[0][1]]
      target2.shift
      tate -= 1
    elsif target1.empty?.!
      ans << [tate+1,i+1]
      ans << [tate+1,target1[0][1]]
      target1.shift
      target2 << [tate+1,i+1]
      tate -= 1
    else
      puts -1
      exit
    end
  end
end
puts ans.length
ans.each do |v|
  puts "#{v[0]} #{v[1]}"
end


from sys import stdin, stdout
def main():
    n = int(stdin.readline())
    a = map(int, stdin.readline().split())
    ans = []
    s = [[], [], [], []]
    for i, x in enumerate(a):
        s[x].append(i)
    r = n - 1
    g = []
    d = []
    t = None
    for i in xrange(n - 1, -1, -1):
        if a[i] == 1:
            ans.append((r, i))
            g.append(i)
        elif a[i] == 2:
            if not g:
                print -1
                return
            x = g.pop()
            ans.append((x, i))
            d.append(x)
        elif a[i] == 3:
            if t is not None:
                pass
            elif d:
                t = d.pop()
            elif g:
                t = g.pop()
            else:
                print -1
                return
            ans.append((r, t))
            ans.append((r, i))
            t = i
        else:
            continue
        r -= 1
    stdout.write(str(len(ans)) + '\n')
    stdout.write('\n'.join('%d %d' % (x, y) for x, y in ans))
main()


from sys import stdin, stdout
def main():
    n = int(stdin.readline())
    a = map(int, stdin.readline().split())
    ans = []
    s = [[], [], [], []]
    for i, x in enumerate(a):
        s[x].append(i)
    r = n - 1
    g = []
    d = []
    t = None
    for i in xrange(n - 1, -1, -1):
        if a[i] == 1:
            ans.append((r, i))
            g.append(i)
        elif a[i] == 2:
            if not g:
                print -1
                return
            x = g.pop()
            ans.append((x, i))
            d.append(i)
        elif a[i] == 3:
            if t is not None:
                pass
            elif d:
                t = d.pop()
            elif g:
                t = g.pop()
            else:
                print -1
                return
            ans.append((r, t))
            ans.append((r, i))
            t = i
        else:
            continue
        r -= 1
    stdout.write(str(len(ans)) + '\n')
    stdout.write('\n'.join('%d %d' % (x + 1, y + 1) for x, y in ans))
main()


from sys import stdin, stdout
def main():
    n = int(stdin.readline())
    a = map(int, stdin.readline().split())
    ans = []
    s = [[], [], [], []]
    for i, x in enumerate(a):
        s[x].append(i)
    r = n - 1
    g = []
    d = []
    t = None
    for i in xrange(n - 1, -1, -1):
        if a[i] == 1:
            ans.append((r, i))
            g.append((r, i))
            r -= 1
        elif a[i] == 2:
            if not g:
                print -1
                return
            x = g.pop()[0]
            ans.append((x, i))
            d.append(i)
        elif a[i] == 3:
            if t is not None:
                pass
            elif d:
                t = d.pop()
            elif g:
                t = g.pop()[1]
            else:
                print -1
                return
            ans.append((r, t))
            ans.append((r, i))
            t = i
            r -= 1
    stdout.write(str(len(ans)) + '\n')
    stdout.write('\n'.join('%d %d' % (x + 1, y + 1) for x, y in ans))
main()


from sys import stdin, stdout
def main():
    n = int(stdin.readline())
    a = map(int, stdin.readline().split())
    ans = []
    s = [[], [], [], []]
    for i, x in enumerate(a):
        s[x].append(i)
    r = n - 1
    g = []
    d = []
    t = None
    for i in xrange(n - 1, -1, -1):
        if a[i] == 1:
            ans.append((r, i))
            g.append(i)
        elif a[i] == 2:
            if not g:
                print -1
                return
            x = g.pop()
            ans.append((x, i))
            d.append(x)
        elif a[i] == 3:
            if t is not None:
                pass
            elif d:
                t = d.pop()
            elif g:
                t = g.pop()
            else:
                print -1
                return
            ans.append((r, t))
            ans.append((r, i))
            t = i
        else:
            continue
        r -= 1
    stdout.write(str(len(ans)) + '\n')
    stdout.write('\n'.join('%d %d' % (x + 1, y + 1) for x, y in ans))
main()


function For(a, b, fn) {
  if (!fn) return For(0, a - 1, b);
  let res;
  for (let i = a; i <= b; i++) {
    if ((res = fn(i)) != null) return res;
  }
}
function ForR(a, b, fn) {
  if (!fn) return ForR(a - 1, 0, b);
  let res;
  for (let i = a; i >= b; i--) {
    if ((res = fn(i)) != null) return res;
  }
}

function Arr(a, b, fn) {
  if (typeof (b) == 'function') return Arr(0, a - 1, b);
  if (b < a) return [];
  let arr = Array(b - a + 1)
  for (let i = a; i <= b; i++) arr[i - a] = fn(i, arr);
  return arr;
}

Object.defineProperty(Object.prototype, '$k', {
  value: function () { return Object.keys(this) }
});
Object.defineProperty(Object.prototype, '$v', {
  value: function () { return Object.values(this) }
});
Object.defineProperty(Object.prototype, '$kv', {
  value: function () { return Object.entries(this) }
});
Array.prototype.sum = function (fn) { return this.reduce((p, v) => p + (fn ? fn(v) : v), 0) }
Array.prototype.uniq = function (fn) {
  var set = new Set();
  return this.filter(v => {
    var newValue = !set.has(fn ? fn(v) : v);
    set.add(fn ? fn(v) : v);
    return newValue;
  });
}
Array.prototype.toObj = function (fn) {
  return this.map(v => fn ? fn(v) : v).reduce((p, v) => {
    p[v[0]] = v[1];
    return p;
  }, {})
}
Array.prototype.min = function (fn) {
  let min = 1e20, index = -1, x;
  for (let i = 0; i < this.length; i++) {
    x = fn ? fn(this[i], i, this) : this[i];
    if (x < min) { min = x; index = i }
  }
  return [this[index], index, min];
}
Array.prototype.max = function (fn) {
  let max = -1e20, index = -1, x;
  for (let i = 0; i < this.length; i++) {
    x = fn ? fn(this[i], i, this) : this[i];
    if (x > max) { max = x; index = i }
  }
  return [this[index], index, max];
}
Array.prototype.rev = function (first, last) {
  for (let i = first; i < (first + last) / 2; i++) {
    [this[i], this[last - 1 - i + first]] = [this[last - 1 - i + first], this[i]]
  }
}
Array.prototype.set = function (pos, arr) {
  for (let i = pos; i < pos + arr.length; i++) {
    this[i] = arr[i - pos];
  }
}
Array.prototype.bin = function (comp, a, b) {
  let mid;
  while (a < b) {
    mid = (a + b) / 2 | 0;
    if (typeof comp == 'function' ? comp(this[mid]) : this[mid] < comp) a = mid + 1;
    else b = mid;
  }
  return a;
}
Array.prototype.cut = function (fn, a, b) {
  let arr = [];
  a = a || 0;
  b = b || (this.length - 1);
  let prev = a;
  for (let i = a; i <= b; i++) {
    if (i == b || fn(this[i], this[i + 1], i, this)) {
      arr.push(this.slice(prev, i + 1));
      prev = i + 1;
    }
  }
  return arr;
}

function gcd(a, b) {
  while (b) [a, b] = [b, a % b];
  return a;
}
function mul(a, b, m) {
  return ((a >> 16) * b % m * 65536 + (a & 65535) * b) % m
}
function pow(a, n, m) {
  let r = 1;
  while (n) n & 1 ? (r = mul(r, a, m), n--) : [a, n] = [mul(a, a, m), n >> 1]
  return r;
}
function inv(b, m) {
  for (var a = m, u = 0, v = 1, t; b; v = t)
    (t = a / b | 0, a -= t * b, u -= t * v, t = a, a = b, b = t, t = u, u = v);
  return (u + m) % m;
}

// let MOD = 1e9 + 7
// let gt = Arr(n, (i, a) => i == 0 ? 1 : mul(a[i - 1], i, MOD));
// let rgt = Arr(n, (i, a) => i <= 1 ? 1 : MOD - mul((MOD / i | 0), a[MOD % i], MOD));
// For(2, n - 1, i => { rgt[i] = mul(rgt[i], rgt[i - 1], MOD) });
// let nCk = (n, k) => mul(mul(gt[n], rgt[k], MOD), rgt[n - k], MOD);

// for (i = pos; i <= n; i += i & -i) fen[i]++; // start from index 1
// for (i = pos; i; i -= i & -i) ans += fen[i];

// let p = [2];
// for (let i = 3; i < 1e5; i += 2) {
//   let j, x = Math.sqrt(i);
//   for (j = 0; p[j] <= x; j++) if (i % p[j] == 0) break;
//   if (i % p[j] != 0) p.push(i);
// }

// let root = x => par[x] < 0 ? x : (par[x] = root(par[x]));
// let dsu = (x, y) => {
//   if ((x = root(x)) == (y = root(y))) return;
//   if (par[y] < par[x]) [x, y] = [y, x];
//   par[x] += par[y];
//   par[y] = x;
// }
// alpha = "abcdefghijklmnopqrstuvwxyz"

let input = '';
process.stdin.on('data', c => input += c);
process.stdin.on('end', main);
async function main() {
  let inp = input.split(/\s+/).map(v => +v), _i = 0, $ = n => n != null ? inp.slice(_i, _i += n) : inp[_i++],
    out = [], log = console.log, asc = (a, b) => a - b, desc = (a, b) => b - a, { min, max, ceil, floor, sqrt, abs, log2 } = Math,
    bi = BigInt, rand = n => Math.random() * n | 0;

  let n = $(), a = $(n)
  let r = n;
  let rc = Arr(n, i => 0)
  let fr = n - 1;
  ForR(n, i => {
    if (a[i] == 0) return;
    if (a[i] == 1) {
      r--;
      rc[r] = 1;
      out.push([r + 1, i + 1])
    } else if (a[i] == 2) {
      while (fr >= 0 && rc[fr] != 1) fr--;
      if (fr < 0) {
        log(-1);
        process.exit()
      }
      rc[fr] = 2;
      out.push([fr + 1, i + 1])
    } else {
      if (!out.length) {
        log(-1);
        process.exit();
      }
      r--;
      rc[r] = 2;
      let x = out[out.length - 1];
      rc[x[0] - 1] = 2;
      out.push([r + 1, x[1]])
      out.push([r + 1, i + 1])
    }
  })
  log(out.length);
  log(out.map(v => v.join(' ')).join('\n'));
}


function For(a, b, fn) {
  if (!fn) return For(0, a - 1, b);
  let res;
  for (let i = a; i <= b; i++) {
    if ((res = fn(i)) != null) return res;
  }
}
function ForR(a, b, fn) {
  if (!fn) return ForR(a - 1, 0, b);
  let res;
  for (let i = a; i >= b; i--) {
    if ((res = fn(i)) != null) return res;
  }
}

function Arr(a, b, fn) {
  if (typeof (b) == 'function') return Arr(0, a - 1, b);
  if (b < a) return [];
  let arr = Array(b - a + 1)
  for (let i = a; i <= b; i++) arr[i - a] = fn(i, arr);
  return arr;
}

Object.defineProperty(Object.prototype, '$k', {
  value: function () { return Object.keys(this) }
});
Object.defineProperty(Object.prototype, '$v', {
  value: function () { return Object.values(this) }
});
Object.defineProperty(Object.prototype, '$kv', {
  value: function () { return Object.entries(this) }
});
Array.prototype.sum = function (fn) { return this.reduce((p, v) => p + (fn ? fn(v) : v), 0) }
Array.prototype.uniq = function (fn) {
  var set = new Set();
  return this.filter(v => {
    var newValue = !set.has(fn ? fn(v) : v);
    set.add(fn ? fn(v) : v);
    return newValue;
  });
}
Array.prototype.toObj = function (fn) {
  return this.map(v => fn ? fn(v) : v).reduce((p, v) => {
    p[v[0]] = v[1];
    return p;
  }, {})
}
Array.prototype.min = function (fn) {
  let min = 1e20, index = -1, x;
  for (let i = 0; i < this.length; i++) {
    x = fn ? fn(this[i], i, this) : this[i];
    if (x < min) { min = x; index = i }
  }
  return [this[index], index, min];
}
Array.prototype.max = function (fn) {
  let max = -1e20, index = -1, x;
  for (let i = 0; i < this.length; i++) {
    x = fn ? fn(this[i], i, this) : this[i];
    if (x > max) { max = x; index = i }
  }
  return [this[index], index, max];
}
Array.prototype.rev = function (first, last) {
  for (let i = first; i < (first + last) / 2; i++) {
    [this[i], this[last - 1 - i + first]] = [this[last - 1 - i + first], this[i]]
  }
}
Array.prototype.set = function (pos, arr) {
  for (let i = pos; i < pos + arr.length; i++) {
    this[i] = arr[i - pos];
  }
}
Array.prototype.bin = function (comp, a, b) {
  let mid;
  while (a < b) {
    mid = (a + b) / 2 | 0;
    if (typeof comp == 'function' ? comp(this[mid]) : this[mid] < comp) a = mid + 1;
    else b = mid;
  }
  return a;
}
Array.prototype.cut = function (fn, a, b) {
  let arr = [];
  a = a || 0;
  b = b || (this.length - 1);
  let prev = a;
  for (let i = a; i <= b; i++) {
    if (i == b || fn(this[i], this[i + 1], i, this)) {
      arr.push(this.slice(prev, i + 1));
      prev = i + 1;
    }
  }
  return arr;
}

function gcd(a, b) {
  while (b) [a, b] = [b, a % b];
  return a;
}
function mul(a, b, m) {
  return ((a >> 16) * b % m * 65536 + (a & 65535) * b) % m
}
function pow(a, n, m) {
  let r = 1;
  while (n) n & 1 ? (r = mul(r, a, m), n--) : [a, n] = [mul(a, a, m), n >> 1]
  return r;
}
function inv(b, m) {
  for (var a = m, u = 0, v = 1, t; b; v = t)
    (t = a / b | 0, a -= t * b, u -= t * v, t = a, a = b, b = t, t = u, u = v);
  return (u + m) % m;
}

// let MOD = 1e9 + 7
// let gt = Arr(n, (i, a) => i == 0 ? 1 : mul(a[i - 1], i, MOD));
// let rgt = Arr(n, (i, a) => i <= 1 ? 1 : MOD - mul((MOD / i | 0), a[MOD % i], MOD));
// For(2, n - 1, i => { rgt[i] = mul(rgt[i], rgt[i - 1], MOD) });
// let nCk = (n, k) => mul(mul(gt[n], rgt[k], MOD), rgt[n - k], MOD);

// for (i = pos; i <= n; i += i & -i) fen[i]++; // start from index 1
// for (i = pos; i; i -= i & -i) ans += fen[i];

// let p = [2];
// for (let i = 3; i < 1e5; i += 2) {
//   let j, x = Math.sqrt(i);
//   for (j = 0; p[j] <= x; j++) if (i % p[j] == 0) break;
//   if (i % p[j] != 0) p.push(i);
// }

// let root = x => par[x] < 0 ? x : (par[x] = root(par[x]));
// let dsu = (x, y) => {
//   if ((x = root(x)) == (y = root(y))) return;
//   if (par[y] < par[x]) [x, y] = [y, x];
//   par[x] += par[y];
//   par[y] = x;
// }
// alpha = "abcdefghijklmnopqrstuvwxyz"

let input = '';
process.stdin.on('data', c => input += c);
process.stdin.on('end', main);
async function main() {
  let inp = input.split(/\s+/).map(v => +v), _i = 0, $ = n => n != null ? inp.slice(_i, _i += n) : inp[_i++],
    out = [], log = console.log, asc = (a, b) => a - b, desc = (a, b) => b - a, { min, max, ceil, floor, sqrt, abs, log2 } = Math,
    bi = BigInt, rand = n => Math.random() * n | 0;

  let n = $(), a = $(n)
  let r = n;
  let rc = Arr(n, i => 0)
  let fr = n - 1;
  ForR(n, i => {
    if (a[i] == 0) return;
    if (a[i] == 1) {
      r--;
      rc[r] = 1;
      out.push([r + 1, i + 1])
    } else if (a[i] == 2) {
      while (fr >= 0 && rc[fr] != 1) fr--;
      if (fr < 0) {
        log(-1);
        process.exit()
      }
      rc[fr] = 2;
      out.push([fr + 1, i + 1])
    } else {
      if (!out.length) {
        log(-1);
        process.exit();
      }
      r--;
      rc[r] = 2;
      out.push([r + 1, out[out.length - 1][1]])
      out.push([r + 1, i + 1])
    }
  })
  log(out.length);
  log(out.map(v => v.join(' ')).join('\n'));
}


process.stdin.resume();
process.stdin.setEncoding('utf-8');

let inputString = '';
let currentLine = 0;

process.stdin.on('data', inputStdin => {
    inputString += inputStdin;
});

process.stdin.on('end', _ => {
    inputString = inputString.trim().split('\n').map(string => string.trim());

    main();
});

function readLine() {
    return inputString[currentLine++];
}

function main() {
    const n = Number.parseInt(readLine());
    const expectedColHits = readLine().split(' ').map(h => Number.parseInt(h));
    let targets = [];
    let nextRow = 0;
    try {
        for (let i = 0; i < expectedColHits.length; i++) {
            if (expectedColHits[i] === 1) {
                targets.push([nextRow++, i]);
            } else if (expectedColHits[i] === 2) {
                targets.push([nextRow, i]);
                targets.push([nextRow++, nextCol1(expectedColHits, i)])
            } else if (expectedColHits[i] === 3) {
                const col = nextColGreater0(expectedColHits, i);
                targets.push([nextRow, i]);
                targets.push([nextRow++, col])
            }
        }
    } catch (e) {
        console.log(-1);
        return;
    }
    if (nextRow > n) {
        console.log(-1);
        return;
    }
    console.log(targets.length);
    for (let i = 0; i < targets.length; i++) {
        console.log(targets[i][0] + 1, targets[i][1] + 1);
    }
}

function nextCol1(expectedColHits, i) {
    for (let k = i+1; k < expectedColHits.length; k++) {
        if (expectedColHits[k] === 1) {
            expectedColHits[k] = 0;
            return k;
        }
    }
    throw new Error();
}
function nextColGreater0(expectedColHits, i) {
    for (let k = i+1; k < expectedColHits.length; k++) {
        if (expectedColHits[k] > 0) {
            return k;
        }
    }
    throw new Error();
}


process.stdin.resume();
process.stdin.setEncoding('utf-8');

let inputString = '';
let currentLine = 0;

process.stdin.on('data', inputStdin => {
    inputString += inputStdin;
});

process.stdin.on('end', _ => {
    inputString = inputString.trim().split('\n').map(string => string.trim());

    main();
});

function readLine() {
    return inputString[currentLine++];
}

function main() {
    const n = Number.parseInt(readLine());
    const expectedColHits = readLine().split(' ').map(h => Number.parseInt(h));
    let targets = 0;
    let nextRow = 0;
    let answer = '';
    try {
        for (let i = 0; i < expectedColHits.length; i++) {
            if (expectedColHits[i] === 1) {
                targets++;
                answer += (nextRow++ + 1) + ' ' + (i + 1) + '\n';
            } else if (expectedColHits[i] === 2) {
                targets += 2;
                answer += (nextRow + 1) + ' ' + (i + 1) + '\n';
                answer += (nextRow++ + 1) + ' ' + (1 + nextCol1(expectedColHits, i)) + '\n';
            } else if (expectedColHits[i] === 3) {
                targets += 2;
                answer += (nextRow + 1) + ' ' + (i + 1) + '\n';
                answer += (nextRow++ + 1) + ' ' + (1 + nextColGreater0(expectedColHits, i)) + '\n';
            }
        }
    } catch (e) {
        console.log(-1);
        return;
    }
    if (nextRow > n) {
        console.log(-1);
        return;
    }
    console.log(targets);
    console.log(answer);
}

function nextCol1(expectedColHits, i) {
    for (let k = i+1; k < expectedColHits.length; k++) {
        if (expectedColHits[k] === 1) {
            expectedColHits[k] = 0;
            return k;
        }
    }
    throw new Error();
}
function nextColGreater0(expectedColHits, i) {
    for (let k = i+1; k < expectedColHits.length; k++) {
        if (expectedColHits[k] > 0) {
            return k;
        }
    }
    throw new Error();
}


process.stdin.resume();
process.stdin.setEncoding('utf-8');

let inputString = '';
let currentLine = 0;

process.stdin.on('data', inputStdin => {
    inputString += inputStdin;
});

process.stdin.on('end', _ => {
    inputString = inputString.trim().split('\n').map(string => string.trim());

    main();
});

function readLine() {
    return inputString[currentLine++];
}

function main() {
    const n = Number.parseInt(readLine());
    const expectedColHits = readLine().split(' ').map(h => Number.parseInt(h));
    let targets = [];
    let nextRow = 0;
    try {
        for (let i = 0; i < expectedColHits.length; i++) {
            if (expectedColHits[i] === 1) {
                targets.push([nextRow++, i]);
            } else if (expectedColHits[i] === 2) {
                targets.push([nextRow, i]);
                targets.push([nextRow++, nextCol(expectedColHits, i)])
            } else if (expectedColHits[i] === 3) {
                const col = nextCol(expectedColHits, i);
                targets.push([nextRow, i]);
                targets.push([nextRow++, col])
                targets.push([nextRow++, col])
            }
        }
    } catch (e) {
        console.log(-1);
        return;
    }
    if (nextRow > n) {
        console.log(-1);
        return;
    }
    console.log(targets.length);
    for (let i = 0; i < targets.length; i++) {
        console.log(targets[i][0] + 1, targets[i][1] + 1);
    }
}

function nextCol(expectedColHits, i) {
    for (let k = i; k < expectedColHits.length; k++) {
        if (expectedColHits[k] === 1) {
            expectedColHits[k] = 0;
            return k;
        }
    }
    throw new Error();
}


process.stdin.resume();
process.stdin.setEncoding('utf-8');

let inputString = '';
let currentLine = 0;

process.stdin.on('data', inputStdin => {
    inputString += inputStdin;
});

process.stdin.on('end', _ => {
    inputString = inputString.trim().split('\n').map(string => string.trim());

    main();
});

function readLine() {
    return inputString[currentLine++];
}

function main() {
    const n = Number.parseInt(readLine());
    const expectedColHits = readLine().split(' ').map(h => Number.parseInt(h));
    let targets = 0;
    let nextRow = 0;
    let answer = '';
    try {
        for (let i = 0; i < expectedColHits.length; i++) {
            if (expectedColHits[i] === 1) {
                targets++;
                answer += nextRow++ + ' ' + i + '\n';
            } else if (expectedColHits[i] === 2) {
                targets += 2;
                answer += nextRow++ + ' ' + i + '\n';
                answer += nextRow++ + ' ' + nextCol1(expectedColHits, i) + '\n';
            } else if (expectedColHits[i] === 3) {
                targets += 2;
                answer += nextRow++ + ' ' + i + '\n';
                answer += nextRow++ + ' ' + nextColGreater0(expectedColHits, i) + '\n';
            }
        }
    } catch (e) {
        console.log(-1);
        return;
    }
    if (nextRow > n) {
        console.log(-1);
        return;
    }
    console.log(targets);
    console.log(answer);
}

function nextCol1(expectedColHits, i) {
    for (let k = i+1; k < expectedColHits.length; k++) {
        if (expectedColHits[k] === 1) {
            expectedColHits[k] = 0;
            return k;
        }
    }
    throw new Error();
}
function nextColGreater0(expectedColHits, i) {
    for (let k = i+1; k < expectedColHits.length; k++) {
        if (expectedColHits[k] > 0) {
            return k;
        }
    }
    throw new Error();
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using CompLib.Util;
using System.Threading;

public class Program
{
    private int N;
    private int[] A;

    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        A = sc.IntArray();

        /*
         * n*nグリッド
         *
         * 下から投げる
         *
         * ぶつかったら90度右向く
         *
         * i列から投げるとA_i回ぶつかる
         *
         *
         */

        /*
         * 0回 置かない
         *
         * 1回 ユニークな列選ぶ
         *
         * 2回 適当な行選んで 一番左　以降の1にぶつける
         *
         * 3回 ユニークな行 一番左の1にぶつける
         */

        var ls = new List<(int r, int c)>();
        int lastR = N;
        int lastC = N;

        // 0スキップ
        // 1 ユニークな行に置く キューに入れる
        // 2 キューから1個出してぶつける キュー2に入れる
        // 3 キュー2 ,キューの順位で出してユニークな行に置く、ぶつける キュー2に入れる

        var q1 = new Queue<(int r, int c)>();
        var q2 = new Queue<int>();
        for (int i = N - 1; i >= 0; i--)
        {
            switch (A[i])
            {
                case 0:
                    break;
                case 1:
                    lastR--;
                    ls.Add((lastR, i));
                    q1.Enqueue((lastR, i));
                    break;
                case 2:
                    if (q1.Count <= 0)
                    {
                        Console.WriteLine("-1");
                        return;
                    }

                    var d = q1.Dequeue();
                    ls.Add((d.r, i));
                    q2.Enqueue(i);
                    break;
                case 3:
                    lastR--;
                    if (q2.Count > 0)
                    {
                        var d2 = q2.Dequeue();
                        ls.Add((lastR, i));
                        ls.Add((lastR, d2));
                        q2.Enqueue(i);
                    }
                    else if (q1.Count > 0)
                    {
                        var d1 = q1.Dequeue();
                        ls.Add((lastR, i));
                        ls.Add((lastR, d1.c));
                        q2.Enqueue(i);
                    }
                    else
                    {
                        Console.WriteLine("-1");
                        return;
                    }
                    break;
            }
        }

        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) {AutoFlush = false});
        Console.WriteLine(ls.Count);
        foreach ((int r, int c) in ls)
        {
            Console.WriteLine($"{r + 1} {c + 1}");
        }

        Console.Out.Flush();
    }

    public static void Main(string[] args) => new Program().Solve();
    // public static void Main(string[] args) => new Thread(new Program().Solve, 1 << 27).Start();
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public string ReadLine()
        {
            _index = _line.Length;
            return Console.ReadLine();
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Text;
using System.Diagnostics;
using System.Numerics;
using static System.Console;
using static System.Convert;
using static System.Math;
using static Template;
using SC = Scanner;

public partial class Solver
{
    public void Solve()
    {
        var N = sc.Int;
        var A = sc.ArrInt;
        var st = new Stack<int>();var tw = new Stack<int>();
        var min = 1;var max = N;
        var res = new List<(int r, int c)>();
        for (int i = N - 1; i >= 0; i--)
        {
            if (A[i] == 0) continue;
            if (A[i] == 1)
            {
                st.Push(i);
                continue;
            }
            if (A[i] == 2)
            {
                if (st.Count == 0) Fail(-1);
                var p = st.Pop();
                res.Add((max, i + 1));
                res.Add((max, p + 1));
                tw.Push(i);max--;
                continue;
            }
            if (A[i] == 3)
            {
                if (st.Count == 0&&tw.Count==0) Fail(-1);
                if (tw.Any())
                {
                    var p = tw.Pop();
                    res.Add((min, p + 1));
                    res.Add((min, i + 1));min++;
                }
                else
                {
                    var p = st.Pop();
                    res.Add((max-1, i + 1));
                    res.Add((max-1, p + 1));
                    res.Add((max, p + 1));max -= 2;
                    tw.Push(i);
                }
            }
        }
        while (st.Any())
        {
            res.Add((min++, st.Pop() + 1));
        }
        Console.WriteLine(res.Count);
        if (res.Count != 0)
        {
            Console.WriteLine(res.Select(v => $"{v.r} {v.c}").Concat("\n"));
        }
    }
}

#region Template
public partial class Solver
{
    public SC sc = new SC();
    static void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        var sol = new Solver();
        int testcase = 1;
        //testcase = sol.sc.Int;
        //var th = new Thread(sol.Solve, 1 << 26);th.Start();th.Join();
        while (testcase-- > 0)
            sol.Solve();
        Console.Out.Flush();
    }
}
public static class Template
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) > 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(this IList<T> A, int i, int j) { var t = A[i]; A[i] = A[j]; A[j] = t; }
    public static T[] Create<T>(int n, Func<T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(); return rt; }
    public static T[] Create<T>(int n, Func<int, T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(i); return rt; }
    public static void Out<T>(this IList<T> A, out T a) => a = A[0];
    public static void Out<T>(this IList<T> A, out T a, out T b) { a = A[0]; b = A[1]; }
    public static void Out<T>(this IList<T> A, out T a, out T b, out T c) { A.Out(out a, out b); c = A[2]; }
    public static void Out<T>(this IList<T> A, out T a, out T b, out T c, out T d) { A.Out(out a, out b, out c); d = A[3]; }
    public static string Concat<T>(this IEnumerable<T> A, string sp) => string.Join(sp, A);
    public static char ToChar(this int s, char begin = '0') => (char)(s + begin);
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> A) => A.OrderBy(v => Guid.NewGuid());
    public static int CompareTo<T>(this T[] A, T[] B, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; for (var i = 0; i < Min(A.Length, B.Length); i++) { int c = cmp(A[i], B[i]); if (c > 0) return 1; else if (c < 0) return -1; } if (A.Length == B.Length) return 0; if (A.Length > B.Length) return 1; else return -1; }
    public static string ToStr<T>(this T[][] A) => A.Select(a => a.Concat(" ")).Concat("\n");
    public static int ArgMax<T>(this IList<T> A, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; T max = A[0]; int rt = 0; for (int i = 1; i < A.Count; i++) if (cmp(max, A[i]) < 0) { max = A[i]; rt = i; } return rt; }
    public static T PopBack<T>(this List<T> A) { var v = A[A.Count - 1]; A.RemoveAt(A.Count - 1); return v; }
    public static void Fail<T>(T s) { Console.WriteLine(s); Console.Out.Close(); Environment.Exit(0); }
}
public class Scanner
{
    public string Str => Console.ReadLine().Trim();
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public int[] ArrInt => Str.Split(' ').Select(int.Parse).ToArray();
    public long[] ArrLong => Str.Split(' ').Select(long.Parse).ToArray();
    public char[][] Grid(int n) => Create(n, () => Str.ToCharArray());
    public int[] ArrInt1D(int n) => Create(n, () => Int);
    public long[] ArrLong1D(int n) => Create(n, () => Long);
    public int[][] ArrInt2D(int n) => Create(n, () => ArrInt);
    public long[][] ArrLong2D(int n) => Create(n, () => ArrLong);
    private Queue<string> q = new Queue<string>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Next<T>() { if (q.Count == 0) foreach (var item in Str.Split(' ')) q.Enqueue(item); return (T)Convert.ChangeType(q.Dequeue(), typeof(T)); }
    public void Make<T1>(out T1 v1) => v1 = Next<T1>();
    public void Make<T1, T2>(out T1 v1, out T2 v2) { v1 = Next<T1>(); v2 = Next<T2>(); }
    public void Make<T1, T2, T3>(out T1 v1, out T2 v2, out T3 v3) { Make(out v1, out v2); v3 = Next<T3>(); }
    public void Make<T1, T2, T3, T4>(out T1 v1, out T2 v2, out T3 v3, out T4 v4) { Make(out v1, out v2, out v3); v4 = Next<T4>(); }
    public void Make<T1, T2, T3, T4, T5>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5) { Make(out v1, out v2, out v3, out v4); v5 = Next<T5>(); }
    public void Make<T1, T2, T3, T4, T5, T6>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6) { Make(out v1, out v2, out v3, out v4, out v5); v6 = Next<T6>(); }
    public void Make<T1, T2, T3, T4, T5, T6, T7>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6, out T7 v7) { Make(out v1, out v2, out v3, out v4, out v5, out v6); v7 = Next<T7>(); }
    public (T1, T2) Make<T1, T2>() { Make(out T1 v1, out T2 v2); return (v1, v2); }
    public (T1, T2, T3) Make<T1, T2, T3>() { Make(out T1 v1, out T2 v2, out T3 v3); return (v1, v2, v3); }
    public (T1, T2, T3, T4) Make<T1, T2, T3, T4>() { Make(out T1 v1, out T2 v2, out T3 v3, out T4 v4); return (v1, v2, v3, v4); }
}

#endregion


using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading;
using System.Runtime.CompilerServices;
using System.Text;
using System.Diagnostics;
using System.Numerics;
using static System.Console;
using static System.Convert;
using static System.Math;
using static Template;
using SC = Scanner;

public partial class Solver
{
    public void Solve()
    {
        var N = sc.Int;
        var A = sc.ArrInt;
        var st = new Stack<int>();var tw = new Stack<int>();
        var min = 1;var max = N;
        var res = new List<(int r, int c)>();
        for (int i = N - 1; i >= 0; i--)
        {
            if (A[i] == 0) continue;
            if (A[i] == 1)
            {
                st.Push(i);
                continue;
            }
            if (A[i] == 2)
            {
                if (st.Count == 0) Fail(-1);
                var p = st.Pop();
                res.Add((max, i + 1));
                res.Add((max, p + 1));
                tw.Push(i);max--;
                continue;
            }
            if (A[i] == 3)
            {
                if (st.Count == 0&&tw.Count==0) Fail(-1);
                if (tw.Any())
                {
                    var p = tw.Pop();
                    res.Add((max, i + 1));
                    res.Add((max, p + 1));max--;
                    tw.Push(i);
                }
                else
                {
                    var p = st.Pop();
                    res.Add((max-1, i + 1));
                    res.Add((max-1, p + 1));
                    res.Add((max, p + 1));max -= 2;
                    tw.Push(i);
                }
            }
        }
        while (st.Any())
        {
            res.Add((min++, st.Pop() + 1));
        }
        Console.WriteLine(res.Count);
        if (res.Count != 0)
        {
            Console.WriteLine(res.Select(v => $"{v.r} {v.c}").Concat("\n"));
        }
    }
}

#region Template
public partial class Solver
{
    public SC sc = new SC();
    static void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        var sol = new Solver();
        int testcase = 1;
        //testcase = sol.sc.Int;
        //var th = new Thread(sol.Solve, 1 << 26);th.Start();th.Join();
        while (testcase-- > 0)
            sol.Solve();
        Console.Out.Flush();
    }
}
public static class Template
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) > 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(this IList<T> A, int i, int j) { var t = A[i]; A[i] = A[j]; A[j] = t; }
    public static T[] Create<T>(int n, Func<T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(); return rt; }
    public static T[] Create<T>(int n, Func<int, T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(i); return rt; }
    public static void Out<T>(this IList<T> A, out T a) => a = A[0];
    public static void Out<T>(this IList<T> A, out T a, out T b) { a = A[0]; b = A[1]; }
    public static void Out<T>(this IList<T> A, out T a, out T b, out T c) { A.Out(out a, out b); c = A[2]; }
    public static void Out<T>(this IList<T> A, out T a, out T b, out T c, out T d) { A.Out(out a, out b, out c); d = A[3]; }
    public static string Concat<T>(this IEnumerable<T> A, string sp) => string.Join(sp, A);
    public static char ToChar(this int s, char begin = '0') => (char)(s + begin);
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> A) => A.OrderBy(v => Guid.NewGuid());
    public static int CompareTo<T>(this T[] A, T[] B, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; for (var i = 0; i < Min(A.Length, B.Length); i++) { int c = cmp(A[i], B[i]); if (c > 0) return 1; else if (c < 0) return -1; } if (A.Length == B.Length) return 0; if (A.Length > B.Length) return 1; else return -1; }
    public static string ToStr<T>(this T[][] A) => A.Select(a => a.Concat(" ")).Concat("\n");
    public static int ArgMax<T>(this IList<T> A, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; T max = A[0]; int rt = 0; for (int i = 1; i < A.Count; i++) if (cmp(max, A[i]) < 0) { max = A[i]; rt = i; } return rt; }
    public static T PopBack<T>(this List<T> A) { var v = A[A.Count - 1]; A.RemoveAt(A.Count - 1); return v; }
    public static void Fail<T>(T s) { Console.WriteLine(s); Console.Out.Close(); Environment.Exit(0); }
}
public class Scanner
{
    public string Str => Console.ReadLine().Trim();
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public int[] ArrInt => Str.Split(' ').Select(int.Parse).ToArray();
    public long[] ArrLong => Str.Split(' ').Select(long.Parse).ToArray();
    public char[][] Grid(int n) => Create(n, () => Str.ToCharArray());
    public int[] ArrInt1D(int n) => Create(n, () => Int);
    public long[] ArrLong1D(int n) => Create(n, () => Long);
    public int[][] ArrInt2D(int n) => Create(n, () => ArrInt);
    public long[][] ArrLong2D(int n) => Create(n, () => ArrLong);
    private Queue<string> q = new Queue<string>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Next<T>() { if (q.Count == 0) foreach (var item in Str.Split(' ')) q.Enqueue(item); return (T)Convert.ChangeType(q.Dequeue(), typeof(T)); }
    public void Make<T1>(out T1 v1) => v1 = Next<T1>();
    public void Make<T1, T2>(out T1 v1, out T2 v2) { v1 = Next<T1>(); v2 = Next<T2>(); }
    public void Make<T1, T2, T3>(out T1 v1, out T2 v2, out T3 v3) { Make(out v1, out v2); v3 = Next<T3>(); }
    public void Make<T1, T2, T3, T4>(out T1 v1, out T2 v2, out T3 v3, out T4 v4) { Make(out v1, out v2, out v3); v4 = Next<T4>(); }
    public void Make<T1, T2, T3, T4, T5>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5) { Make(out v1, out v2, out v3, out v4); v5 = Next<T5>(); }
    public void Make<T1, T2, T3, T4, T5, T6>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6) { Make(out v1, out v2, out v3, out v4, out v5); v6 = Next<T6>(); }
    public void Make<T1, T2, T3, T4, T5, T6, T7>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6, out T7 v7) { Make(out v1, out v2, out v3, out v4, out v5, out v6); v7 = Next<T7>(); }
    public (T1, T2) Make<T1, T2>() { Make(out T1 v1, out T2 v2); return (v1, v2); }
    public (T1, T2, T3) Make<T1, T2, T3>() { Make(out T1 v1, out T2 v2, out T3 v3); return (v1, v2, v3); }
    public (T1, T2, T3, T4) Make<T1, T2, T3, T4>() { Make(out T1 v1, out T2 v2, out T3 v3, out T4 v4); return (v1, v2, v3, v4); }
}

#endregion