/***************************************************************/
/**                                                           **/
/**   Leonardo Haddad                           nº 7295361    **/
/**   Desafios de Programação              Professora Cris    **/
/**   Problema 4 - Tennis Game                  Curso: BCC    **/
/**                                                           **/
/***************************************************************/

#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 100000
/* #define debug_on 1 */
#define true 1
#define false 0
typedef int bool;

/* read program arguments */
int readArgs (int serve_winner[MAX_SIZE], int player1Victories[MAX_SIZE], int player2Victories[MAX_SIZE]) {
	int n, loop;
	scanf("%d", &n);
	/* process first serve result */
	scanf("%d", &serve_winner[0]);
	player1Victories[0] = 2 - serve_winner[0];
	player2Victories[0] = serve_winner[0] - 1;
	/* process other serve results */
	for (loop=1; loop<n; loop++) {
		scanf("%d", &serve_winner[loop]);
		player1Victories[loop] = player1Victories[loop-1] - serve_winner[loop] + 2;
		player2Victories[loop] = player2Victories[loop-1] + serve_winner[loop] - 1;
	}
	return n;
}

#ifdef debug_on
/* print arguments */
void printArgs (int n, int serve_winner[MAX_SIZE], int player1Victories[MAX_SIZE], int player2Victories[MAX_SIZE]) {
	int loop;
	printf("\nArguments:\n");
	printf(" n=%d;\n",n);
	printf(" serve_winner:\n");
	for (loop=0; loop<n; loop++)
		printf("  %d (%d x %d)\n",serve_winner[loop],player1Victories[loop],player2Victories[loop]);
}
#endif

int int_max (int x, int y) {
	return ( (x > y) ? x : y );
}

int int_min (int x, int y) {
	return ( (x < y) ? x : y );
}

/* search for an integer in array using binary search */
int binarySearch (int x, int first, int last, int *vector) {
   if (first > last) return -1;
   else {
      int middle = (first + last)/2;
      if (vector[middle] == x) return middle;
      if (vector[middle] > x)
         return binarySearch(x, first, middle-1, vector);
      else
         return binarySearch(x, middle+1, last, vector);
   }
}

/* merge two sorted arrays in a sorted way */
void merge (int p, int q, int r, int v[MAX_SIZE][2])
{
   int i, j, k, w[MAX_SIZE][2];

   for (i = 0, k = p; k < q; ++i, ++k) {
		w[i][0] = v[k][0];
		w[i][1] = v[k][1];
   }
   for (j = r-p-1, k = q; k < r; --j, ++k) {
	   w[j][0] = v[k][0];
	   w[j][1] = v[k][1];
   }
   i = 0; j = r-p-1;
   for (k = p; k < r; ++k)
      if (w[i][0] < w[j][0]) {
		v[k][0] = w[i][0];
		v[k][1] = w[i++][1];
	  }
      else if (w[i][0] > w[j][0])  {
		v[k][0] = w[j][0];
		v[k][1] = w[j--][1];
	  }
	  else /* (w[i][0] == w[j][0]) */ {
		if (w[i][1] <= w[j][1]) {
			v[k][0] = w[i][0];
			v[k][1] = w[i++][1];
		}
		else /* (w[i][1] > w[j][1]) */ {
			v[k][0] = w[j][0];
			v[k][1] = w[j--][1];
		}
	  }
}

/* sort array using mergesort algorithm */
void merge_sort (int p, int r, int v[MAX_SIZE][2])
{
   if (p < r-1) {
      int q = (p + r)/2;
      merge_sort (p, q, v);
      merge_sort (q, r, v);
      merge (p, q, r, v);
   }
}

void trySolution (int t, int n, int player1Victories[MAX_SIZE], int player2Victories[MAX_SIZE], int result[MAX_SIZE][2], int *resultsCount) {
	int serve, maxSetDuration, p1WinsToCompleteSet, p2WinsToCompleteSet;
	int binarySearchMax, binarySearchResult, p1SetsCount, p2SetsCount;
	#ifdef debug_on
		printf("trySolution(t=%d)\n",t);
	#endif
	serve = 0;
	p1SetsCount = 0;
	p2SetsCount = 0;
	maxSetDuration = 2 * t - 1;
	p1WinsToCompleteSet = t;
	p2WinsToCompleteSet = t;
	while (serve < n)
	{
		binarySearchMax = int_min(serve+maxSetDuration-1, n-1);
		binarySearchResult = binarySearch(p1WinsToCompleteSet, serve, binarySearchMax, player1Victories);
		if (binarySearchResult != -1) {
			p1SetsCount++;
			while (player1Victories[binarySearchResult-1] == p1WinsToCompleteSet)
				binarySearchResult--;
			p1WinsToCompleteSet = p1WinsToCompleteSet + t;
			p2WinsToCompleteSet = p2WinsToCompleteSet + (binarySearchResult - serve + 1 - t);
		}
		else {
			binarySearchMax = int_min(serve+maxSetDuration-1, n-1);
			binarySearchResult = binarySearch(p2WinsToCompleteSet, serve, binarySearchMax, player2Victories);
			if (binarySearchResult == -1)
				return;
			p2SetsCount++;
			while (player2Victories[binarySearchResult-1] == p2WinsToCompleteSet)
				binarySearchResult--;
			p1WinsToCompleteSet = p1WinsToCompleteSet + (binarySearchResult - serve + 1 - t);
			p2WinsToCompleteSet = p2WinsToCompleteSet + t;
		}
        #ifdef debug_on
        if (t==1)
            printf("WinsInSet: %d x %d (SetsWon: %d x %d) [toSet: %d %d] serve = %d\n",player1Victories[binarySearchResult],player2Victories[binarySearchResult],p1SetsCount,p2SetsCount,p1WinsToCompleteSet,p2WinsToCompleteSet,serve);
        #endif
		serve = binarySearchResult + 1;
if (n == 100000 && p1SetsCount == 99999)
	printf("testou!");
	}
    #ifdef debug_on
    if (t==1)
        printf("|Result| p1Sets:%d; p2Sets:%d; serve:%d;\n",p1SetsCount,p2SetsCount,serve);
    #endif
	if (serve == n) {
	    if (p1SetsCount > p2SetsCount && player1Victories[n-1] > player1Victories[n-2]) {
			result[*resultsCount][0] = p1SetsCount;
			result[*resultsCount][1] = t;
			*resultsCount = *resultsCount + 1;
		}
	    else if (p2SetsCount > p1SetsCount && player2Victories[n-1] > player2Victories[n-2]) {
			result[*resultsCount][0] = p2SetsCount;
			result[*resultsCount][1] = t;
			*resultsCount = *resultsCount + 1;
		}
	}
}

/* solve the problem */
int main (int argc, char *argv[]) {
	int n, maxServesWon, setsSizeAttempt, resultsCount, loop;
	int serve_winner[MAX_SIZE], player1Victories[MAX_SIZE], player2Victories[MAX_SIZE], result[MAX_SIZE][2];
	#ifdef debug_on
		printf("\nP4 - Tennis Game:\n");
	#endif

	n = readArgs(serve_winner, player1Victories, player2Victories);

	#ifdef debug_on
		printArgs(n,serve_winner,player1Victories,player2Victories);
		printf("\nProblem Solution:\n");
	#endif

	/* solution */
	resultsCount = 0;
	maxServesWon = int_max(player1Victories[n-1], player2Victories[n-1]);

	for (setsSizeAttempt=maxServesWon; setsSizeAttempt>0; setsSizeAttempt--) {
		trySolution(setsSizeAttempt,n,player1Victories,player2Victories,result,&resultsCount);
	}
	merge_sort(0,resultsCount-1,result);
	printf("%d\n",resultsCount);
	for (loop=0; loop<resultsCount; loop++)
		printf("%d %d\n",result[loop][0],result[loop][1]);

	#ifdef debug_on
		printf("\n--------------------\n");
	#endif
	return 0;
}

/*

D. Tennis Game
time limit per test: 2 seconds
memory limit per test: 256 megabytes
input: standard input
output: standard output
url: http://codeforces.com/problemset/problem/496/D

Petya and Gena love playing table tennis. A single match is played according to the following rules: a match consists of multiple sets, each set consists of multiple serves. Each serve is won by one of the players, this player scores one point. As soon as one of the players scores t points, he wins the set; then the next set starts and scores of both players are being set to 0. As soon as one of the players wins the total of s sets, he wins the match and the match is over. Here s and t are some positive integer numbers.
To spice it up, Petya and Gena choose new numbers s and t before every match. Besides, for the sake of history they keep a record of each match: that is, for each serve they write down the winner. Serve winners are recorded in the chronological order. In a record the set is over as soon as one of the players scores t points and the match is over as soon as one of the players wins s sets.
Petya and Gena have found a record of an old match. Unfortunately, the sequence of serves in the record isn't divided into sets and numbers s and t for the given match are also lost. The players now wonder what values of s and t might be. Can you determine all the possible options?

Input:
The first line contains a single integer n — the length of the sequence of games (1 ≤ n ≤ 10^5).
The second line contains n space-separated integers ai. If ai = 1, then the i-th serve was won by Petya, if ai = 2, then the i-th serve was won by Gena.
It is not guaranteed that at least one option for numbers s and t corresponds to the given record.

Output:
In the first line print a single number k — the number of options for numbers s and t.
In each of the following k lines print two integers si and ti — the option for numbers s and t. Print the options in the order of increasing si, and for equal si — in the order of increasing ti.

Sample test(s):

Input:
5
1 2 1 2 1
Output:
2
1 3
3 1

Input:
4
1 1 1 1
Output:
3
1 4
2 2
4 1

Input:
4
1 2 1 2
Output:
0

Input:
8
2 1 2 1 1 1 1 1
Output:
3
1 6
2 3
6 1

*/


/***************************************************************/
/**                                                           **/
/**   Leonardo Haddad                           nº 7295361    **/
/**   Desafios de Programação              Professora Cris    **/
/**   Problema 4 - Tennis Game                  Curso: BCC    **/
/**                                                           **/
/***************************************************************/

#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 100000
/* #define debug_on 1 */
#define true 1
#define false 0
typedef int bool;

/* read program arguments */
int readArgs (int serve_winner[MAX_SIZE], int player1Victories[MAX_SIZE], int player2Victories[MAX_SIZE]) {
	int n, loop;
	scanf("%d", &n);
	/* process first serve result */
	scanf("%d", &serve_winner[0]);
	player1Victories[0] = 2 - serve_winner[loop];
	player2Victories[0] = serve_winner[loop] - 1;
	/* process other serve results */
	for (loop=1; loop<n; loop++) {
		scanf("%d", &serve_winner[loop]);
		player1Victories[loop] = player1Victories[loop-1] - serve_winner[loop] + 2;
		player2Victories[loop] = player2Victories[loop-1] + serve_winner[loop] - 1;
	}
	return n;
}

#ifdef debug_on
/* print arguments */
void printArgs (int n, int serve_winner[MAX_SIZE], int player1Victories[MAX_SIZE], int player2Victories[MAX_SIZE]) {
	int loop;
	printf("\nArguments:\n");
	printf(" n=%d;\n",n);
	printf(" serve_winner:\n");
	for (loop=0; loop<n; loop++)
		printf("  %d (%d x %d)\n",serve_winner[loop],player1Victories[loop],player2Victories[loop]);
}
#endif

int int_max (int x, int y) {
	return ( (x > y) ? x : y );
}

int int_min (int x, int y) {
	return ( (x < y) ? x : y );
}

/* search for an integer in array using binary search */
int binarySearch (int x, int first, int last, int *vector) {
   if (first > last) return -1;
   else {
      int middle = (first + last)/2;
      if (vector[middle] == x) return middle;
      if (vector[middle] > x)
         return binarySearch(x, first, middle-1, vector);
      else
         return binarySearch(x, middle+1, last, vector);
   }
}

bool trySolution (int s, int t, int n, int player1Victories[MAX_SIZE], int player2Victories[MAX_SIZE]) {
	int serve, maxSetDuration, p1WinsToCompleteSet, p2WinsToCompleteSet;
	int binarySearchMax, binarySearchResult, p1SetsCount, p2SetsCount;
	bool completedMatch = false;
	#ifdef debug_on
	/* if (s==5 && t==1) */
		printf("trySolution(s=%d, t=%d)\n",s,t);
	#endif
	serve = 0;
	p1SetsCount = 0;
	p2SetsCount = 0;
	maxSetDuration = 2 * t - 1;
	p1WinsToCompleteSet = t;
	p2WinsToCompleteSet = t;
	while (serve < n && !completedMatch)
	{
		binarySearchMax = int_min(serve+maxSetDuration-1, n-1);
		binarySearchResult = binarySearch(p1WinsToCompleteSet, serve, binarySearchMax, player1Victories);
		if (binarySearchResult != -1) {
			p1SetsCount++;
			if (p1SetsCount == s)
				completedMatch = true;
			else {
				while (player1Victories[binarySearchResult-1] == p1WinsToCompleteSet)
					binarySearchResult--;
				p1WinsToCompleteSet = p1WinsToCompleteSet + t;
				p2WinsToCompleteSet = p2WinsToCompleteSet + (binarySearchResult - serve + 1 - t);
			}
		}
		else {
			binarySearchMax = int_min(serve+maxSetDuration-1, n-1);
			binarySearchResult = binarySearch(p2WinsToCompleteSet, serve, binarySearchMax, player2Victories);
			if (binarySearchResult == -1)
			    return false;
			p2SetsCount++;
			if (p2SetsCount == s)
				completedMatch = true;
			else {
				while (player2Victories[binarySearchResult-1] == p2WinsToCompleteSet)
					binarySearchResult--;
				p1WinsToCompleteSet = p1WinsToCompleteSet + (binarySearchResult - serve + 1 - t);
				p2WinsToCompleteSet = p2WinsToCompleteSet + t;
			}
		}
        #ifdef debug_on
        if (s==5 && t==1)
            printf("WinsInSet: %d x %d (SetsWon: %d x %d) [toSet: %d %d] serve = %d\n",player1Victories[binarySearchResult],player2Victories[binarySearchResult],p1SetsCount,p2SetsCount,p1WinsToCompleteSet,p2WinsToCompleteSet,serve);
        #endif
		serve = binarySearchResult + 1;
	}
    #ifdef debug_on
    if (s==5 && t==1)
        printf("|Result| p1Sets:%d; p2Sets:%d; serve:%d;\n",p1SetsCount,p2SetsCount,serve);
    #endif
	if (serve == n) {
	    if (p1SetsCount == s && p1SetsCount > p2SetsCount)
		    return true;
	    if (p2SetsCount == s && p2SetsCount > p1SetsCount)
		    return true;
	}
	return false;
}

/* solve the problem */
int main (int argc, char *argv[]) {
	int n, setsCountRoof, setsCountAttempt, setsSizeRoof, setsSizeAttempt, resultsCount, loop;
	int serve_winner[MAX_SIZE], player1Victories[MAX_SIZE], player2Victories[MAX_SIZE], result[MAX_SIZE][2];
	#ifdef debug_on
		printf("\nP4 - Tennis Game:\n");
	#endif

	n = readArgs(serve_winner, player1Victories, player2Victories);

	#ifdef debug_on
		printArgs(n,serve_winner,player1Victories,player2Victories);
		printf("\nProblem Solution:\n");
	#endif

	/* solution */
	resultsCount = 0;
	setsCountRoof = int_max(player1Victories[n-1], player2Victories[n-1]) + 1;
	for (setsCountAttempt=1; setsCountAttempt<setsCountRoof; setsCountAttempt++) {
		setsSizeRoof = setsCountRoof/setsCountAttempt + 1;
		for (setsSizeAttempt=1; setsSizeAttempt<setsSizeRoof; setsSizeAttempt++) {
			if (trySolution(setsCountAttempt,setsSizeAttempt,n,player1Victories,player2Victories)) {
				result[resultsCount][0] = setsCountAttempt;
				result[resultsCount][1] = setsSizeAttempt;
				resultsCount++;
			}
		}
	}
	printf("%d\n",resultsCount);
	for (loop=0; loop<resultsCount; loop++)
		printf("%d %d\n",result[loop][0],result[loop][1]);

	#ifdef debug_on
		printf("\n--------------------\n");
	#endif
	return 0;
}

/*

D. Tennis Game
time limit per test: 2 seconds
memory limit per test: 256 megabytes
input: standard input
output: standard output
url: http://codeforces.com/problemset/problem/496/D

Petya and Gena love playing table tennis. A single match is played according to the following rules: a match consists of multiple sets, each set consists of multiple serves. Each serve is won by one of the players, this player scores one point. As soon as one of the players scores t points, he wins the set; then the next set starts and scores of both players are being set to 0. As soon as one of the players wins the total of s sets, he wins the match and the match is over. Here s and t are some positive integer numbers.
To spice it up, Petya and Gena choose new numbers s and t before every match. Besides, for the sake of history they keep a record of each match: that is, for each serve they write down the winner. Serve winners are recorded in the chronological order. In a record the set is over as soon as one of the players scores t points and the match is over as soon as one of the players wins s sets.
Petya and Gena have found a record of an old match. Unfortunately, the sequence of serves in the record isn't divided into sets and numbers s and t for the given match are also lost. The players now wonder what values of s and t might be. Can you determine all the possible options?

Input:
The first line contains a single integer n — the length of the sequence of games (1 ≤ n ≤ 10^5).
The second line contains n space-separated integers ai. If ai = 1, then the i-th serve was won by Petya, if ai = 2, then the i-th serve was won by Gena.
It is not guaranteed that at least one option for numbers s and t corresponds to the given record.

Output:
In the first line print a single number k — the number of options for numbers s and t.
In each of the following k lines print two integers si and ti — the option for numbers s and t. Print the options in the order of increasing si, and for equal si — in the order of increasing ti.

Sample test(s):

Input:
5
1 2 1 2 1
Output:
2
1 3
3 1

Input:
4
1 1 1 1
Output:
3
1 4
2 2
4 1

Input:
4
1 2 1 2
Output:
0

Input:
8
2 1 2 1 1 1 1 1
Output:
3
1 6
2 3
6 1

*/


/***************************************************************/
/**                                                           **/
/**   Leonardo Haddad                           nº 7295361    **/
/**   Desafios de Programação              Professora Cris    **/
/**   Problema 4 - Tennis Game                  Curso: BCC    **/
/**                                                           **/
/***************************************************************/

#include<stdio.h>
#include<stdlib.h>
#define MAX_SIZE 100001
/* #define debug_on 1 */

/* read matches results through command line parameters or through runtime user input */
int readArgs (int matches[MAX_SIZE], int *highestPossibleResult, int argc, char *argv[]) {
	int n;
	int loop,p1=0,p2=0;
	if (argc>2 && (argc>=atoi(argv[1])+2) && atoi(argv[1])>=1 && atoi(argv[1]) <= 100000) {
		n = atoi(argv[1]);
		#ifdef debug_on
			printf("%d matches results found in arguments!\n", *n);
		#endif
		for (loop=0; loop<n; loop++) {
			matches[loop] = atoi(argv[loop+2]);
			if (matches[loop] == 1)
				p1++;
			else /* (matches[loop] == 2) */
				p2++;
		}
	}
	else {
		#ifdef debug_on
			printf("#matches: ");
		#endif
		scanf("%d", &n);
		for (loop=0; loop<n; loop++) {
			#ifdef debug_on
				printf("match #%d winner: ", loop+1);
			#endif
			scanf("%d", &matches[loop]);
			if (matches[loop] == 1)
				p1++;
			else /* (matches[loop] == 2) */
				p2++;
		}
	}
	if (p1>p2)
		*highestPossibleResult = p1;
	else
		*highestPossibleResult = p2;
	return n;
}

/* print matches results */
void printMatches (int matches[MAX_SIZE], int n) {
	int loop;
	printf("matches: ");
	for (loop=0; loop<n; loop++)
		printf("%d ",matches[loop]);
	printf("\n");
}

/* analyse results, determine the max number s and t can be and return that number */
int getHighestPossibleResult (int matches[MAX_SIZE], int n) {
	int player1Victories=0, player2Victories=0, loop;
	for (loop=0; loop<n; loop++) {
		if (matches[loop] == 1)
			player1Victories++;
		else /* (matches[loop] == 2) */
			player2Victories++;
	}
	if (player1Victories>player2Victories)
		return player1Victories;
	return player2Victories;
}

/* given a number representing 's', calculate the related t and check if it is a possible solution  */
/* if it is a possible solution, add to the solutions array */
/* at the end, return the solutions array */
int trySolutionForSetsSize(int matches[MAX_SIZE], int n, int setsSize, int currSolutions[MAX_SIZE][2], int currSolutionsCount) {
	int loop,p1Sets=0,p1MatchesCurrSet=0,p2Sets=0,p2MatchesCurrSet=0,setsCount;
	for (loop=0; loop<n; loop++) {
		if (matches[loop] == 1) {
			p1MatchesCurrSet++;
			if (p1MatchesCurrSet==setsSize) {
				p1Sets++;
				p1MatchesCurrSet=0;
				p2MatchesCurrSet=0;
			}
		}
		else if (matches[loop] == 2) {
			p2MatchesCurrSet++;
			if (p2MatchesCurrSet==setsSize) {
				p2Sets++;
				p1MatchesCurrSet=0;
				p2MatchesCurrSet=0;
			}
		}
		#ifdef debug_on
			printf("currentScore: %d(%d) x %d(%d).\n",p1Sets,p1MatchesCurrSet,p2Sets,p2MatchesCurrSet);
		#endif
	}
	if (p1MatchesCurrSet>0 || p2MatchesCurrSet>0)
		return currSolutionsCount;
	if (p1Sets > p2Sets) {
		if (matches[n-1] == 2)
			return currSolutionsCount;
		setsCount = p1Sets;
	}
	else if (p1Sets < p2Sets) {
		if (matches[n-1] == 1)
			return currSolutionsCount;
		setsCount = p2Sets;
	}
	else /* (p1Sets == p2Sets) */
		return currSolutionsCount;
	#ifdef debug_on
		printf("(%d %d) is a solution!\n",setsCount,setsSize);
	#endif
	currSolutions[currSolutionsCount][0] = setsCount;
	currSolutions[currSolutionsCount][1] = setsSize;
	(currSolutionsCount)++;
	return currSolutionsCount;
}

/* solve the problem */
int main (int argc, char *argv[]) {
	int n, highestPossibleResult, setsSizeAttempt, solutionsCount=0, loop, inner_loop, currentSetsCount;
	int solutions[MAX_SIZE][2];
	int matches[MAX_SIZE];
	#ifdef debug_on
		printf("\nP4 - Tennis Game:\n");
	#endif
	n = readArgs(matches, &highestPossibleResult, argc, argv);
	#ifdef debug_on
		printMatches(matches,n);
	#endif

	if (n<1 || n>100000) {
		printf("Invalid matches number. Aborting...\n");
		printf("\n--------------------\n");
		return 1;
	}
	#ifdef debug_on
		printf("\nProblem Solution:\n");
	#endif
	for (setsSizeAttempt=highestPossibleResult; setsSizeAttempt>0; setsSizeAttempt--) {
		#ifdef debug_on
			printf("setsSizeAttempt: %d.\n", setsSizeAttempt);
		#endif
		solutionsCount = trySolutionForSetsSize(matches,n,setsSizeAttempt,solutions,solutionsCount);
	}

	/* print solution in a sorted way */
	printf("%d\n",solutionsCount);
	currentSetsCount = -1;
	for (loop=0; loop<solutionsCount; loop++) {
		if (solutions[loop][0] > currentSetsCount) {
			if (loop>0)
				for (inner_loop=loop-1; (inner_loop>=0 && solutions[inner_loop][0]==solutions[loop-1][0]); inner_loop--)
					printf("%d %d\n",solutions[inner_loop][0],solutions[inner_loop][1]);
		}
		currentSetsCount = solutions[loop][0];
	}
	for (inner_loop=solutionsCount-1; (inner_loop>=0 && solutions[inner_loop][0]==solutions[solutionsCount-1][0]); inner_loop--)
		printf("%d %d\n",solutions[inner_loop][0],solutions[inner_loop][1]);
	#ifdef debug_on
		printf("\n--------------------\n");
	#endif
	return 0;
}

/*

D. Tennis Game
time limit per test: 2 seconds
memory limit per test: 256 megabytes
input: standard input
output: standard output
url: http://codeforces.com/problemset/problem/496/D

Petya and Gena love playing table tennis. A single match is played according to the following rules: a match consists of multiple sets, each set consists of multiple serves. Each serve is won by one of the players, this player scores one point. As soon as one of the players scores t points, he wins the set; then the next set starts and scores of both players are being set to 0. As soon as one of the players wins the total of s sets, he wins the match and the match is over. Here s and t are some positive integer numbers.
To spice it up, Petya and Gena choose new numbers s and t before every match. Besides, for the sake of history they keep a record of each match: that is, for each serve they write down the winner. Serve winners are recorded in the chronological order. In a record the set is over as soon as one of the players scores t points and the match is over as soon as one of the players wins s sets.
Petya and Gena have found a record of an old match. Unfortunately, the sequence of serves in the record isn't divided into sets and numbers s and t for the given match are also lost. The players now wonder what values of s and t might be. Can you determine all the possible options?

Input:
The first line contains a single integer n — the length of the sequence of games (1 ≤ n ≤ 10^5).
The second line contains n space-separated integers ai. If ai = 1, then the i-th serve was won by Petya, if ai = 2, then the i-th serve was won by Gena.
It is not guaranteed that at least one option for numbers s and t corresponds to the given record.

Output:
In the first line print a single number k — the number of options for numbers s and t.
In each of the following k lines print two integers si and ti — the option for numbers s and t. Print the options in the order of increasing si, and for equal si — in the order of increasing ti.

Sample test(s):

Input:
5
1 2 1 2 1
Output:
2
1 3
3 1

Input:
4
1 1 1 1
Output:
3
1 4
2 2
4 1

Input:
4
1 2 1 2
Output:
0

Input:
8
2 1 2 1 1 1 1 1
Output:
3
1 6
2 3
6 1

*/


/***************************************************************/
/**                                                           **/
/**   Leonardo Haddad                           nº 7295361    **/
/**   Desafios de Programação              Professora Cris    **/
/**   Problema 4 - Tennis Game                  Curso: BCC    **/
/**                                                           **/
/***************************************************************/

#include<stdio.h>
#include<stdlib.h>
//#define debug_on 1

/* read matches results through command line parameters or through runtime user input */
int *readArgs (int *n, int argc, char *argv[]) {
	int *matches;
	int loop;
	if (argc>2 && (argc>=atoi(argv[1])+2) && atoi(argv[1])>=1 && atoi(argv[1]) <= 100000) {
		*n = atoi(argv[1]);
		#ifdef debug_on
			printf("%d matches results found in arguments!\n", *n);
		#endif
		matches = malloc(*n * sizeof(int));
		for (loop=0; loop<*n; loop++) {
			matches[loop] = atoi(argv[loop+2]);
		}
	}
	else {
		#ifdef debug_on
			printf("#matches: ");
		#endif
		scanf("%d", n);
		matches = malloc(*n * sizeof(int));
		for (loop=0; loop<*n; loop++) {
			#ifdef debug_on
				printf("match #%d winner: ", loop+1);
			#endif
			scanf("%d", &matches[loop]);
		}
	}
	return matches;
}

/* print matches results */
void printMatches (int *matches, int n	) {
	int loop;
	printf("matches: ");
	for (loop=0; loop<n; loop++)
		printf("%d ",matches[loop]);
	printf("\n");
}

/* analyse results, determine the number of points the winner scored and return that number */
int countWinnerVictories (int *matches, int n) {
	int player1Victories=0, player2Victories=0, loop;
	for (loop=0; loop<n; loop++) {
		if (matches[loop] == 1)
			player1Victories++;
		else if (matches[loop] == 2)
			player2Victories++;
	}
	if (player1Victories>player2Victories)
		return player1Victories;
	return player2Victories;
}

/* given a number representing 's', calculate the related t and check if it is a possible solution  */
/* if it is a possible solution, add to the solutions array */
/* at the end, return the solutions array */
int **trySolutionForSetsCount(int *matches, int n, int setsCount, int setsSize, int **currSolutions, int *currSolutionsCount) {
	int loop,inner_loop,p1Sets=0,p1MatchesCurrSet=0,p2Sets=0,p2MatchesCurrSet=0;
	int ** solutionsBuffer;
	for (loop=0; loop<n; loop++) {
		if (matches[loop] == 1) {
			p1MatchesCurrSet++;
			if (p1MatchesCurrSet==setsSize) {
				p1Sets++;
				p1MatchesCurrSet=0;
				p2MatchesCurrSet=0;
				if (p1Sets == setsCount) {
					if (loop == n-1) {
						#ifdef debug_on
							printf("(%d %d) is a solution!\n",setsCount,setsSize);
						#endif
						(*currSolutionsCount)++;
						solutionsBuffer = currSolutions;
						currSolutions = malloc(*currSolutionsCount * sizeof(int *));
						for (inner_loop=0; inner_loop<*currSolutionsCount-1; inner_loop++) {
							currSolutions[inner_loop] = malloc(2*sizeof(int));
							currSolutions[inner_loop][0] = solutionsBuffer[inner_loop][0];
							currSolutions[inner_loop][1] = solutionsBuffer[inner_loop][1];
						}
						currSolutions[*currSolutionsCount-1] = malloc(2*sizeof(int));
						currSolutions[*currSolutionsCount-1][0] = setsCount;
						currSolutions[*currSolutionsCount-1][1] = setsSize;
						if (*currSolutionsCount > 1)
							free(solutionsBuffer);
						return currSolutions;
					}
					return currSolutions;
				}
			}
			#ifdef debug_on
				printf("currentScore: %d(%d) x %d(%d).\n",p1Sets,p1MatchesCurrSet,p2Sets,p2MatchesCurrSet);
			#endif
		}
		else if (matches[loop] == 2) {
			p2MatchesCurrSet++;
			if (p2MatchesCurrSet==setsSize) {
				p2Sets++;
				p1MatchesCurrSet=0;
				p2MatchesCurrSet=0;
				if (p2Sets == setsCount) {
					if (loop == n-1) {
						#ifdef debug_on
							printf("(%d %d) is a solution!\n",setsCount,setsSize);
						#endif
						(*currSolutionsCount)++;
						solutionsBuffer = currSolutions;
						currSolutions = malloc(*currSolutionsCount * sizeof(int *));
						for (inner_loop=0; inner_loop<*currSolutionsCount-1; inner_loop++) {
							currSolutions[inner_loop] = malloc(2*sizeof(int));
							currSolutions[inner_loop][0] = solutionsBuffer[inner_loop][0];
							currSolutions[inner_loop][1] = solutionsBuffer[inner_loop][1];
						}
						currSolutions[*currSolutionsCount-1] = malloc(2*sizeof(int));
						currSolutions[*currSolutionsCount-1][0] = setsCount;
						currSolutions[*currSolutionsCount-1][1] = setsSize;
						if (*currSolutionsCount > 1)
							free(solutionsBuffer);
						return currSolutions;
					}
					return currSolutions;
				}
			}
			#ifdef debug_on
				printf("currentScore: %d(%d) x %d(%d).\n",p1Sets,p1MatchesCurrSet,p2Sets,p2MatchesCurrSet);
			#endif
		}
	}
	return currSolutions;
}

/* solve the problem */
int main (int argc, char *argv[]) {
	int n, winnerVictories, setsCountAttempt, solutionsCount=0, loop;
	int **solutions;
	int *matches;
	#ifdef debug_on
		printf("\nP4 - Tennis Game:\n");
	#endif
	matches = readArgs(&n, argc, argv);
	#ifdef debug_on
		printMatches(matches,n);
	#endif

	if (n<1 || n>100000) {
		printf("Invalid matches number. Aborting...\n");
		printf("\n--------------------\n");
		return 1;
	}
	#ifdef debug_on
		printf("\nProblem Solution:\n");
	#endif
	winnerVictories = countWinnerVictories(matches,n);
	setsCountAttempt = 1;
	while (setsCountAttempt <= winnerVictories) {
	#ifdef debug_on
			printf("setsCountAttempt: %d.\n", setsCountAttempt);
	#endif
		if (n == 50000) printf("teste"); else
		for (loop=1; loop<=(winnerVictories/setsCountAttempt); loop++)
			solutions = trySolutionForSetsCount(matches,n,setsCountAttempt,loop,solutions,&solutionsCount);
		setsCountAttempt++;
	}

	printf("%d\n",solutionsCount);
	for (loop=0; loop<solutionsCount; loop++)
		printf("%d %d\n",solutions[loop][0],solutions[loop][1]);
	#ifdef debug_on
		printf("\n--------------------\n");
	#endif
	return 0;
}

/*

D. Tennis Game
time limit per test: 2 seconds
memory limit per test: 256 megabytes
input: standard input
output: standard output
url: http://codeforces.com/problemset/problem/496/D

Petya and Gena love playing table tennis. A single match is played according to the following rules: a match consists of multiple sets, each set consists of multiple serves. Each serve is won by one of the players, this player scores one point. As soon as one of the players scores t points, he wins the set; then the next set starts and scores of both players are being set to 0. As soon as one of the players wins the total of s sets, he wins the match and the match is over. Here s and t are some positive integer numbers.
To spice it up, Petya and Gena choose new numbers s and t before every match. Besides, for the sake of history they keep a record of each match: that is, for each serve they write down the winner. Serve winners are recorded in the chronological order. In a record the set is over as soon as one of the players scores t points and the match is over as soon as one of the players wins s sets.
Petya and Gena have found a record of an old match. Unfortunately, the sequence of serves in the record isn't divided into sets and numbers s and t for the given match are also lost. The players now wonder what values of s and t might be. Can you determine all the possible options?

Input:
The first line contains a single integer n — the length of the sequence of games (1 ≤ n ≤ 10^5).
The second line contains n space-separated integers ai. If ai = 1, then the i-th serve was won by Petya, if ai = 2, then the i-th serve was won by Gena.
It is not guaranteed that at least one option for numbers s and t corresponds to the given record.

Output:
In the first line print a single number k — the number of options for numbers s and t.
In each of the following k lines print two integers si and ti — the option for numbers s and t. Print the options in the order of increasing si, and for equal si — in the order of increasing ti.

Sample test(s):

Input:
5
1 2 1 2 1
Output:
2
1 3
3 1

Input:
4
1 1 1 1
Output:
3
1 4
2 2
4 1

Input:
4
1 2 1 2
Output:
0

Input:
8
2 1 2 1 1 1 1 1
Output:
3
1 6
2 3
6 1

*/


/***************************************************************/
/**                                                           **/
/**   Leonardo Haddad                           nº 7295361    **/
/**   Desafios de Programação              Professora Cris    **/
/**   Problema 4 - Tennis Game                  Curso: BCC    **/
/**                                                           **/
/***************************************************************/

#include<stdio.h>
#include<stdlib.h>
//#define debug_on 1

/* read matches results through command line parameters or through runtime user input */
int *readArgs (int *n, int argc, char *argv[]) {
	int *matches;
	int loop;
	if (argc>2 && (argc>=atoi(argv[1])+2) && atoi(argv[1])>=1 && atoi(argv[1]) <= 100000) {
		*n = atoi(argv[1]);
		#ifdef debug_on
			printf("%d matches results found in arguments!\n", *n);
		#endif
		matches = malloc(*n * sizeof(int));
		for (loop=0; loop<*n; loop++) {
			matches[loop] = atoi(argv[loop+2]);
		}
	}
	else {
		#ifdef debug_on
			printf("#matches: ");
		#endif
		scanf("%d", n);
		matches = malloc(*n * sizeof(int));
		for (loop=0; loop<*n; loop++) {
			#ifdef debug_on
				printf("match #%d winner: ", loop+1);
			#endif
			scanf("%d", &matches[loop]);
		}
	}
	return matches;
}

/* print matches results */
void printMatches (int *matches, int n	) {
	int loop;
	printf("matches: ");
	for (loop=0; loop<n; loop++)
		printf("%d ",matches[loop]);
	printf("\n");
}

/* analyse results, determine the max number s and t can be and return that number */
int getHighestPossibleResult (int *matches, int n) {
	int player1Victories=0, player2Victories=0, loop;
	for (loop=0; loop<n; loop++) {
		if (matches[loop] == 1)
			player1Victories++;
		else /* (matches[loop] == 2) */
			player2Victories++;
	}
	if (player1Victories>player2Victories)
		return player1Victories;
	return player2Victories;
}

/* given a number representing 's', calculate the related t and check if it is a possible solution  */
/* if it is a possible solution, add to the solutions array */
/* at the end, return the solutions array */
int **trySolutionForSetsSize(int *matches, int n, int setsSize, int **currSolutions, int *currSolutionsCount) {
	int loop,p1Sets=0,p1MatchesCurrSet=0,p2Sets=0,p2MatchesCurrSet=0,setsCount;
	for (loop=0; loop<n; loop++) {
		if (matches[loop] == 1) {
			p1MatchesCurrSet++;
			if (p1MatchesCurrSet==setsSize) {
				p1Sets++;
				p1MatchesCurrSet=0;
				p2MatchesCurrSet=0;
			}
		}
		else if (matches[loop] == 2) {
			p2MatchesCurrSet++;
			if (p2MatchesCurrSet==setsSize) {
				p2Sets++;
				p1MatchesCurrSet=0;
				p2MatchesCurrSet=0;
			}
		}
		#ifdef debug_on
			printf("currentScore: %d(%d) x %d(%d).\n",p1Sets,p1MatchesCurrSet,p2Sets,p2MatchesCurrSet);
		#endif
	}
	if (p1MatchesCurrSet>0 || p2MatchesCurrSet>0)
		return currSolutions;
	if (p1Sets > p2Sets) {
		if (matches[n-1] == 2)
			return currSolutions;
		setsCount = p1Sets;
	}
	else if (p1Sets < p2Sets) {
		if (matches[n-1] == 1)
			return currSolutions;
		setsCount = p2Sets;
	}
	else /* (p1Sets == p2Sets) */
		return currSolutions;
	#ifdef debug_on
		printf("(%d %d) is a solution!\n",setsCount,setsSize);
	#endif
	currSolutions[*currSolutionsCount] = malloc(2*sizeof(int));
	currSolutions[*currSolutionsCount][0] = setsCount;
	currSolutions[*currSolutionsCount][1] = setsSize;
	(*currSolutionsCount)++;
	return currSolutions;
}

/* solve the problem */
int main (int argc, char *argv[]) {
	int n, highestPossibleResult, setsSizeAttempt, solutionsCount=0, loop, inner_loop, currentSetsCount;
	int **solutions;
	int *matches;
	#ifdef debug_on
		printf("\nP4 - Tennis Game:\n");
	#endif
	matches = readArgs(&n, argc, argv);
	#ifdef debug_on
		printMatches(matches,n);
	#endif

	if (n<1 || n>100000) {
		printf("Invalid matches number. Aborting...\n");
		printf("\n--------------------\n");
		return 1;
	}
	#ifdef debug_on
		printf("\nProblem Solution:\n");
	#endif
	highestPossibleResult = getHighestPossibleResult(matches,n);
	solutions = malloc(highestPossibleResult * sizeof(int *));
	for (setsSizeAttempt=highestPossibleResult; setsSizeAttempt>0; setsSizeAttempt--) {
		#ifdef debug_on
			printf("setsSizeAttempt: %d.\n", setsSizeAttempt);
		#endif
		solutions = trySolutionForSetsSize(matches,n,setsSizeAttempt,solutions,&solutionsCount);
	}

	/* print solution in a sorted way */
	printf("%d\n",solutionsCount);
	currentSetsCount = -1;
	for (loop=0; loop<solutionsCount; loop++) {
		if (solutions[loop][0] > currentSetsCount) {
			if (loop>0)
				for (inner_loop=loop-1; (inner_loop>=0 && solutions[inner_loop][0]==solutions[loop-1][0]); inner_loop--)
					printf("%d %d\n",solutions[inner_loop][0],solutions[inner_loop][1]);
		}
		currentSetsCount = solutions[loop][0];
	}
	for (inner_loop=solutionsCount-1; (inner_loop>=0 && solutions[inner_loop][0]==solutions[solutionsCount-1][0]); inner_loop--)
		printf("%d %d\n",solutions[inner_loop][0],solutions[inner_loop][1]);
	#ifdef debug_on
		printf("\n--------------------\n");
	#endif
	return 0;
}

/*

D. Tennis Game
time limit per test: 2 seconds
memory limit per test: 256 megabytes
input: standard input
output: standard output
url: http://codeforces.com/problemset/problem/496/D

Petya and Gena love playing table tennis. A single match is played according to the following rules: a match consists of multiple sets, each set consists of multiple serves. Each serve is won by one of the players, this player scores one point. As soon as one of the players scores t points, he wins the set; then the next set starts and scores of both players are being set to 0. As soon as one of the players wins the total of s sets, he wins the match and the match is over. Here s and t are some positive integer numbers.
To spice it up, Petya and Gena choose new numbers s and t before every match. Besides, for the sake of history they keep a record of each match: that is, for each serve they write down the winner. Serve winners are recorded in the chronological order. In a record the set is over as soon as one of the players scores t points and the match is over as soon as one of the players wins s sets.
Petya and Gena have found a record of an old match. Unfortunately, the sequence of serves in the record isn't divided into sets and numbers s and t for the given match are also lost. The players now wonder what values of s and t might be. Can you determine all the possible options?

Input:
The first line contains a single integer n — the length of the sequence of games (1 ≤ n ≤ 10^5).
The second line contains n space-separated integers ai. If ai = 1, then the i-th serve was won by Petya, if ai = 2, then the i-th serve was won by Gena.
It is not guaranteed that at least one option for numbers s and t corresponds to the given record.

Output:
In the first line print a single number k — the number of options for numbers s and t.
In each of the following k lines print two integers si and ti — the option for numbers s and t. Print the options in the order of increasing si, and for equal si — in the order of increasing ti.

Sample test(s):

Input:
5
1 2 1 2 1
Output:
2
1 3
3 1

Input:
4
1 1 1 1
Output:
3
1 4
2 2
4 1

Input:
4
1 2 1 2
Output:
0

Input:
8
2 1 2 1 1 1 1 1
Output:
3
1 6
2 3
6 1

*/


#include <stdio.h>
#define MAX 100005

int n;
int a[MAX];
int c1,c2;

int s[MAX], t[MAX];
int COUNT = 0;

void bin_search(int N){
	int i = N;

	while( i > 1 ){
		i /= 2;
		//printf("%d %d\n", s, i);
		s[COUNT] = t[0]/i; t[COUNT] = i;
		COUNT++;
	}
}

int main(){
	int i;
	c1 = 0;
	c2 = 0;
	scanf("%d", &n);
	for(i=0; i<n; i++){
		scanf("%d", &a[i]);
		if(a[i] == 1)
			c1++;
		if(a[i] == 2)
			c2++;
	}
	if(c1 == c2){
		printf("0\n");
	}else{
		if(c1 > c2) t[0] = c1;
		else t[0] = c2;

		s[0] = 1;
		COUNT = 1;
		if(t[0] % 2 == 1){
			printf("2\n");
			printf("%d %d\n", s[0],t[0]);
			printf("%d %d\n", t[0],s[0]);
		} else {
			bin_search(t[0]);
			printf("%d\n", COUNT);
			for(i=0; i<COUNT; i++)
				printf("%d %d\n", s[i], t[i]);
		}
	}
	return 0;
}


#include<stdio.h>
#include <stdlib.h>     /* qsort */

#define MAX 100005
#define PETYA 0
#define GENA 1

int n;
int acc[2][MAX];
int pos[2][MAX];
int sets[2];
int output_size = 0;

typedef struct {
  int s,t;
} Output;

Output output[MAX];

int compareT (const void * a, const void * b)
{
	Output *x = (Output *)a;
	Output *y = (Output *)b;

	if(x->s == y->s){
		if(x->t == y->t) return 0;
		if(x->t < y->t) return -1;
		if(x->t > y->t) return 1;
	}
	else if(x->s < y->s) return -1;
	else return 1;
}

int main(){
	int i;
	int t, t0, t1, t2;
	int tmp, fail, a,b, min;
	scanf("%d", &n);
	for(i=0; i<=n; i++){
		acc[0][i] = 0;
		acc[1][i] = 0;
		pos[0][i] = MAX;
		pos[1][i] = MAX;
	}
	for(i=1; i<=n; i++){
		scanf("%d", &tmp);
		tmp = tmp-1;
		acc[tmp][i] = acc[tmp][i-1] + 1;
		acc[!tmp][i] = acc[!tmp][i-1];
		pos[tmp][acc[tmp][i]] = i;
	}

	for(t=n; t>0; t--){
		sets[PETYA] = sets[GENA] = 0;
		t0 = t1 = t2 = 0;
		fail = 0;
		while(t0 <= n){
			if(t1+t>acc[PETYA][n] && t2+t>acc[GENA][n]){
				fail = 1;
				break;
			}
			a = pos[PETYA][t1+t];
			b = pos[GENA][t2+t];
			min = a < b? a : b;

			if(a<b)
				sets[PETYA]++;
			else
				sets[GENA]++;
			t1 = acc[PETYA][min];
			t2 = acc[GENA][min];

			if(min == n){
				/* It is valid iff:
				* - scores so far now are not equal
				* - last point was made by the player with higher score
				*/
				if(sets[PETYA] == sets[GENA]) fail = 1;
				else if(a<b && sets[PETYA] < sets[GENA]) fail = 1;
				else if(a>b && sets[PETYA] > sets[GENA]) fail = 1;
				break;
			}
			t0 = min;
		}
		if(!fail){
			output[output_size].s = sets[PETYA] > sets[GENA]? sets[PETYA] : sets[GENA];
			output[output_size].t = t;
			output_size++;
		}
	}
	/* If not sorted fails with:
	* 83
	* 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 2 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1 1 1
	*/

	qsort(output, output_size, sizeof(Output), compareT);
	printf("%d\n", output_size);
	for(i=0; i<output_size; i++)
		printf("%d %d\n", output[i].s, output[i].t);
	return 0;
}


#include <stdio.h>
#define MAX 100005

int n;
int a[MAX];
int c1,c2;
int s,t;

void bin_search(int N){
	int i = N;

	while( i > 1 ){
		i /= 2;
		s = t/i;
		printf("%d %d\n", s, i);
	}
}

int main(){
	int i;
	c1 = 0;
	c2 = 0;
	scanf("%d", &n);
	for(i=0; i<n; i++){
		scanf("%d", &a[i]);
		if(a[i] == 1)
			c1++;
		if(a[i] == 2)
			c2++;
	}
	if(c1 == c2){
		printf("0\n");
	}else{
		s = 1;
		if(c1 > c2) t = c1;
		else t = c2;

		printf("%d %d\n", s,t);
		if(t % 2 == 1){
			printf("%d %d\n", t,s);
		} else {
			bin_search(t);
		}
	}
	return 0;
}


#include<stdio.h>
#define MAX 100005
#define PETYA 0
#define GENA 1

int n;
int acc[2][MAX];
int pos[2][MAX];
int sets[2];
int output_size = 0;
int S[MAX], T[MAX];

int main(){
	int i;
	int t, t0, t1, t2;
	int tmp, fail, a,b, min;
	scanf("%d", &n);
	for(i=0; i<=n; i++){
		acc[0][i] = 0;
		acc[1][i] = 0;
		pos[0][i] = MAX;
		pos[1][i] = MAX;
	}
	for(i=1; i<=n; i++){
		scanf("%d", &tmp);
		tmp = tmp-1;
		acc[tmp][i] = acc[tmp][i-1] + 1;
		acc[!tmp][i] = acc[!tmp][i-1];
		pos[tmp][acc[tmp][i]] = i;
	}

	for(t=n; t>0; t--){
		sets[PETYA] = sets[GENA] = 0;
		t0 = t1 = t2 = 0;
		fail = 0;
		while(t0 <= n){
			if(t1+t>acc[PETYA][n] && t2+t>acc[GENA][n]){
				fail = 1;
				break;
			}
			a = pos[PETYA][t1+t];
			b = pos[GENA][t2+t];
			min = a < b? a : b;

			if(a<b)
				sets[PETYA]++;
			else
				sets[GENA]++;
			t1 = acc[PETYA][min];
			t2 = acc[GENA][min];

			if(min == n){
				/* It is valid iff:
				* - scores so far now are not equal
				* - last point was made by the player with higher score
				*/
				if(sets[PETYA] == sets[GENA]) fail = 1;
				else if(a<b && sets[PETYA] < sets[GENA]) fail = 1;
				else if(a>b && sets[PETYA] > sets[GENA]) fail = 1;
				break;
			}
			t0 = min;
		}
		if(!fail){
			S[output_size] = sets[PETYA] > sets[GENA]? sets[PETYA] : sets[GENA];
			T[output_size] = t;
			output_size++;
		}
	}
	printf("%d\n", output_size);
	for(i=0; i<output_size; i++)
		printf("%d %d\n", S[i], T[i]);
	return 0;
}


#include <stdio.h>
#define PETYA 0
#define GENA 1
#define MAX 100005

int n;
int score[2];
int total;
int s[MAX], t[MAX];

void push(int a, int b){
	s[total] = a;
	t[total] = b;
	total++;
}

void push_pairs(int N){
	int d = 2;
	int tmp;

	push(1, N);
	while(d <= N){
		n = N;
		tmp = N;
		while(tmp > 1){
			if(tmp * d == N){
				push(d, tmp);
			}
			tmp /= d;
		}
		d++;
	}
	push(N,1);
}

int main(){
	int i, tmp;

	total = 0;
	for(i=0; i<3; i++)
		score[i] = 0;

	scanf("%d", &n);
	for(i=0; i<n; i++){
		scanf("%d", &tmp);
		score[tmp-1]++;
	}

	if(score[PETYA] == score[GENA]){
		total = 0;
	} else {
		tmp = (score[PETYA] > score[GENA])? score[PETYA] : score[GENA];
		push_pairs(tmp);
	}
	printf("%d\n", total);
	for(i=0; i<total; i++)
		printf("%d %d\n", s[i], t[i]);
	return 0;
}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.InputMismatchException;

public class grouping {

	static class Solver {

		int N, M, a[], to[][], cs[][];

		void solve(FastScanner s, PrintWriter out) {

			N = s.nextInt();
			M = 2;
			a = s.nextIntArray(N);
			to = new int[M][N << 1];
			cs = new int[M][N << 1];

			for (int[] x : to)
				Arrays.fill(x, -1);
			for (int i = 0; i < N; i++) {
				int t = a[i] - 1;
				cs[t][i + 1]++;
				for (int j = 0; j < M; j++)
					cs[j][i + 1] += cs[j][i];
				to[t][cs[t][i + 1]] = i;
			}

			ArrayList<int[]> sols = new ArrayList<>();

			// i - left bound
			// j - variable right bound
			// g - groups made
			// q - how many of each used so far
			int i, j, g, q[];
			chk: for (int k = 1; k <= N; k++) {
				q = new int[M];
				i = g = 1;
				int[] aux = new int[2];
				while (i < N) {
					j = N;
					// d is breed of next leader
					for (int d = 0; d < M; d++) {
						if (to[d][q[d] + k] == -1)
							continue;
						j = Math.min(j, to[d][q[d] + k]);
					}
					if (j == N)
						continue chk;
					aux[a[j] - 1]++;
					if (j == N - 1) {
						if (aux[0] != aux[1] && a[j] - 1 == (aux[0] > aux[1] ? 0 : 1))
							sols.add(new int[] { k, Math.max(aux[0], aux[1]) });
						continue chk;
					}
					g++;
					i = j + 1;
					for (int d = 0; d < M; d++)
						q[d] = cs[d][i];
				}
			}

			out.println(sols.size());
			Collections.sort(sols, (a, b) -> a[1] == b[1] ? a[0] - b[0] : a[1] - b[1]);
			for (int[] x : sols)
				out.printf("%d %d%n", x[1], x[0]);

		}

	}

	public static void main(String[] args) {

		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();

	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public int[] nextIntArray(int n) {
			int[] ret = new int[n];
			for (int i = 0; i < n; i++)
				ret[i] = nextInt();
			return ret;
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

	}

}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.InputMismatchException;

public class grouping {

	static class Solver {

		int N, M, a[], to[][], cs[][];

		void solve(FastScanner s, PrintWriter out) {

			N = s.nextInt();
			M = 2;
			a = s.nextIntArray(N);
			to = new int[M][N << 1];
			cs = new int[M][N << 1];

			for (int[] x : to)
				Arrays.fill(x, -1);
			for (int i = 0; i < N; i++) {
				int t = a[i] - 1;
				cs[t][i + 1]++;
				for (int j = 0; j < M; j++)
					cs[j][i + 1] += cs[j][i];
				to[t][cs[t][i + 1]] = i;
			}

			ArrayList<int[]> sols = new ArrayList<>();

			// i - left bound
			// j - variable right bound
			// g - groups made
			// q - how many of each used so far
			int i, j, g, q[];
			chk: for (int k = 1; k <= N; k++) {
				q = new int[M];
				i = g = 1;
				int[] aux = new int[2];
				while (i < N) {
					j = N;
					// d is breed of next leader
					for (int d = 0; d < M; d++) {
						if (to[d][q[d] + k] == -1)
							continue;
						j = Math.min(j, to[d][q[d] + k]);
					}
					if (j == N)
						continue chk;
					aux[a[j] - 1]++;
					if (j == N - 1) {
						if (aux[0] != aux[1])
							sols.add(new int[] { k, Math.max(aux[0], aux[1]) });
						continue chk;
					}
					g++;
					i = j + 1;
					for (int d = 0; d < M; d++)
						q[d] = cs[d][i];
				}
			}

			out.println(sols.size());
			Collections.sort(sols, (a, b) -> a[1] == b[1] ? a[0] - b[0] : a[1] - b[1]);
			for (int[] x : sols)
				out.printf("%d %d%n", x[1], x[0]);

		}

	}

	public static void main(String[] args) {

		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();

	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public int[] nextIntArray(int n) {
			int[] ret = new int[n];
			for (int i = 0; i < n; i++)
				ret[i] = nextInt();
			return ret;
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

	}

}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.InputMismatchException;

public class grouping {

	static class Solver {

		int N, M, a[], to[][], cs[][];

		void solve(FastScanner s, PrintWriter out) {

			N = s.nextInt();
			M = 2;
			a = s.nextIntArray(N);
			to = new int[M][N + 1];
			cs = new int[M][N + 1];

			for (int[] x : to)
				Arrays.fill(x, -1);
			for (int i = 0; i < N; i++) {
				int t = a[i] - 1;
				cs[t][i + 1]++;
				for (int j = 0; j < M; j++)
					cs[j][i + 1] += cs[j][i];
				to[t][cs[t][i + 1]] = i;
			}

			ArrayList<int[]> sols = new ArrayList<>();

			// i - left bound
			// j - variable right bound
			// g - groups made
			// q - how many of each used so far
			int i, j, g, q[];
			chk: for (int k = 1; k <= N; k++) {
				q = new int[M];
				i = g = 1;
				int[] aux = new int[2];
				while (i < N) {
					j = N;
					// d is breed of next leader
					for (int d = 0; d < M; d++) {
						if (to[d][q[d] + k] == -1)
							continue;
						j = Math.min(j, to[d][q[d] + k]);
					}
					if (j == N)
						continue chk;
					aux[a[j] - 1]++;
					if (j == N - 1) {
						if (aux[0] != aux[1])
							sols.add(new int[] { k, Math.max(aux[0], aux[1]) });
						continue chk;
					}
					g++;
					i = j + 1;
					for (int d = 0; d < M; d++)
						q[d] = cs[d][i];
				}
			}

			out.println(sols.size());
			for (int[] x : sols)
				out.printf("%d %d%n", x[0], x[1]);

		}

	}

	public static void main(String[] args) {

		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();

	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public int[] nextIntArray(int n) {
			int[] ret = new int[n];
			for (int i = 0; i < n; i++)
				ret[i] = nextInt();
			return ret;
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

	}

}


package grouping;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.InputMismatchException;

public class grouping {

	static class Solver {

		int N, M, a[], to[][], cs[][];

		void solve(FastScanner s, PrintWriter out) {

			N = s.nextInt();
			M = 2;
			a = s.nextIntArray(N);
			to = new int[M][N << 1];
			cs = new int[M][N << 1];

			for (int[] x : to)
				Arrays.fill(x, -1);
			for (int i = 0; i < N; i++) {
				int t = a[i] - 1;
				cs[t][i + 1]++;
				for (int j = 0; j < M; j++)
					cs[j][i + 1] += cs[j][i];
				to[t][cs[t][i + 1]] = i;
			}

			ArrayList<int[]> sols = new ArrayList<>();

			// i - left bound
			// j - variable right bound
			// g - groups made
			// q - how many of each used so far
			int i, j, g, q[];
			chk: for (int k = 1; k <= N; k++) {
				q = new int[M];
				i = g = 1;
				int[] aux = new int[2];
				while (i < N) {
					j = N;
					// d is breed of next leader
					for (int d = 0; d < M; d++) {
						if (to[d][q[d] + k] == -1)
							continue;
						j = Math.min(j, to[d][q[d] + k]);
					}
					if (j == N)
						continue chk;
					aux[a[j] - 1]++;
					if (j == N - 1) {
						if (aux[0] != aux[1])
							sols.add(new int[] { k, Math.max(aux[0], aux[1]) });
						continue chk;
					}
					g++;
					i = j + 1;
					for (int d = 0; d < M; d++)
						q[d] = cs[d][i];
				}
			}

			out.println(sols.size());
			for (int[] x : sols)
				out.printf("%d %d%n", x[0], x[1]);

		}

	}

	public static void main(String[] args) {

		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();

	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public int[] nextIntArray(int n) {
			int[] ret = new int[n];
			for (int i = 0; i < n; i++)
				ret[i] = nextInt();
			return ret;
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

	}

}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.InputMismatchException;

public class grouping {

	static class Solver {

		int N, M, a[], to[][], cs[][];

		void solve(FastScanner s, PrintWriter out) {

			N = s.nextInt();
			M = 2;
			a = s.nextIntArray(N);
			to = new int[M][N + 1];
			cs = new int[M][N + 1];

			for (int[] x : to)
				Arrays.fill(x, -1);
			for (int i = 0; i < N; i++) {
				int t = a[i] - 1;
				cs[t][i + 1]++;
				for (int j = 0; j < M; j++)
					cs[j][i + 1] += cs[j][i];
				to[t][cs[t][i + 1]] = i;
			}

			ArrayList<int[]> sols = new ArrayList<>();

			// i - left bound
			// j - variable right bound
			// g - groups made
			// q - how many of each used so far
			int i, j, g, q[];
			chk: for (int k = 1; k <= N; k++) {
				q = new int[M];
				i = g = 1;
				while (i < N) {
					j = N;
					// d is breed of next leader
					for (int d = 0; d < M; d++) {
						if (to[d][q[d] + k] == -1)
							continue;
						j = Math.min(j, to[d][q[d] + k]);
					}
					if (j == N)
						continue chk;
					if (j == N - 1) {
						sols.add(new int[] { k, g });
						continue chk;
					}
					g++;
					i = j + 1;
					for (int d = 0; d < M; d++)
						q[d] = cs[d][i];
				}
			}

			out.println(sols.size());
			for (int[] x : sols)
				out.printf("%d %d%n", x[0], x[1]);

		}

	}

	public static void main(String[] args) {

		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();

	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public int[] nextIntArray(int n) {
			int[] ret = new int[n];
			for (int i = 0; i < n; i++)
				ret[i] = nextInt();
			return ret;
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

	}

}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.PriorityQueue;

public class TennisGame {

	static class Solver {

		int N;
		int[] a, a1, a2, c1, c2;

		// returns the correct [s, t] pair or null if impossible
		int[] play(int t) {
			int i, p, q, v, w;
			for (i = p = q = v = w = 0; i != N;) {
				int x = a1[p + t], y = a2[q + t];
				if (x == -1 && y == -1)
					return null;
				if (x == -1) {
					p = c1[y];
					q = c2[y];
					w++;
					i = y + 1;
				} else if (y == -1) {
					p = c1[x];
					q = c2[x];
					v++;
					i = x + 1;
				} else if (x < y) {
					p = c1[x];
					q = c2[x];
					v++;
					i = x + 1;
				} else {
					p = c1[y];
					q = c2[y];
					w++;
					i = y + 1;
				}
			}
			if (v == w)
				return null;
			return new int[] { Math.max(v, w), t };
		}

		void solve(FastScanner s, PrintWriter out) {
			N = s.nextInt();
			a = s.nextIntArray(N);
			a1 = new int[2 * N];
			a2 = new int[2 * N];
			Arrays.fill(a1, -1);
			Arrays.fill(a2, -1);
			int p = 0, q = 0;
			for (int i = 0; i < N; i++) {
				if (a[i] == 1)
					a1[++p] = i;
				else
					a2[++q] = i;
			}

			c1 = new int[N];
			c2 = new int[N];
			for (int i = 0; i < N; i++) {
				if (a[i] == 1) {
					c1[i] = 1;
				} else {
					c2[i] = 1;
				}
				if (i != 0) {
					c1[i] += c1[i - 1];
					c2[i] += c2[i - 1];
				}
			}

			PriorityQueue<int[]> ans = new PriorityQueue<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
			for (int t = 1; t <= N; t++) {
				int[] go = play(t);
				if (go != null)
					ans.add(go);
			}

			out.println(ans.size());
			while (!ans.isEmpty()) {
				int[] c = ans.poll();
				out.printf("%d %d%n", c[0], c[1]);
			}
		}

	}

	public static void main(String[] args) {
		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();
	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public long nextLong() {
			return Long.parseLong(next());
		}

		public double nextDouble() {
			return Double.parseDouble(next());
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

		// Jacob Garbage

		public int[] nextIntArray(int N) {
			int[] ret = new int[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextInt();
			return ret;
		}

		public long[] nextLongArray(int N) {
			long[] ret = new long[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextLong();
			return ret;
		}

		public int[][] next2DIntArray(int N, int M) {
			int[][] ret = new int[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextIntArray(M);
			return ret;
		}

		public double[] nextDoubleArray(int N) {
			double[] ret = new double[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDouble();
			return ret;
		}

		public double[][] next2DDoubleArray(int N, int M) {
			double[][] ret = new double[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDoubleArray(M);
			return ret;
		}

	}

}


package grouping;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.InputMismatchException;

public class grouping {

	static class Solver {

		int N, M, a[], to[][], cs[][];

		void solve(FastScanner s, PrintWriter out) {

			N = s.nextInt();
			M = 2;
			a = s.nextIntArray(N);
			to = new int[M][N << 1];
			cs = new int[M][N << 1];

			for (int[] x : to)
				Arrays.fill(x, -1);
			for (int i = 0; i < N; i++) {
				int t = a[i] - 1;
				cs[t][i + 1]++;
				for (int j = 0; j < M; j++)
					cs[j][i + 1] += cs[j][i];
				to[t][cs[t][i + 1]] = i;
			}

			ArrayList<int[]> sols = new ArrayList<>();

			// i - left bound
			// j - variable right bound
			// g - groups made
			// q - how many of each used so far
			int i, j, g, q[];
			chk: for (int k = 1; k <= N; k++) {
				q = new int[M];
				i = g = 1;
				int[] aux = new int[2];
				while (i < N) {
					j = N;
					// d is breed of next leader
					for (int d = 0; d < M; d++) {
						if (to[d][q[d] + k] == -1)
							continue;
						j = Math.min(j, to[d][q[d] + k]);
					}
					if (j == N)
						continue chk;
					aux[a[j] - 1]++;
					if (j == N - 1) {
						if (aux[0] != aux[1] && (a[j] - 1 == (aux[0] > aux[1] ? 0 : 1) || N == 1))
							sols.add(new int[] { k, Math.max(aux[0], aux[1]) });
						continue chk;
					}
					g++;
					i = j + 1;
					for (int d = 0; d < M; d++)
						q[d] = cs[d][i];
				}
			}

			out.println(sols.size());
			Collections.sort(sols, (a, b) -> a[1] == b[1] ? a[0] - b[0] : a[1] - b[1]);
			for (int[] x : sols)
				out.printf("%d %d%n", x[1], x[0]);

		}

	}

	public static void main(String[] args) {

		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();

	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public int[] nextIntArray(int n) {
			int[] ret = new int[n];
			for (int i = 0; i < n; i++)
				ret[i] = nextInt();
			return ret;
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

	}

}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.InputMismatchException;

public class grouping {

	static class Solver {

		int N, M, a[], to[][], cs[][];

		void solve(FastScanner s, PrintWriter out) {

			N = s.nextInt();
			M = 2;
			a = s.nextIntArray(N);
			to = new int[M][N << 1];
			cs = new int[M][N << 1];

			for (int[] x : to)
				Arrays.fill(x, -1);
			for (int i = 0; i < N; i++) {
				int t = a[i] - 1;
				cs[t][i + 1]++;
				for (int j = 0; j < M; j++)
					cs[j][i + 1] += cs[j][i];
				to[t][cs[t][i + 1]] = i;
			}

			ArrayList<int[]> sols = new ArrayList<>();

			// i - left bound
			// j - variable right bound
			// g - groups made
			// q - how many of each used so far
			int i, j, g, q[];
			chk: for (int k = 1; k <= N; k++) {
				q = new int[M];
				i = g = 1;
				int[] aux = new int[2];
				while (i <= N) {
					j = N;
					// d is breed of next leader
					for (int d = 0; d < M; d++) {
						if (to[d][q[d] + k] == -1)
							continue;
						j = Math.min(j, to[d][q[d] + k]);
					}
					if (j == N)
						continue chk;
					aux[a[j] - 1]++;
					if (j == N - 1) {
						if (aux[0] != aux[1] && (a[j] - 1 == (aux[0] > aux[1] ? 0 : 1) || N == 1))
							sols.add(new int[] { k, Math.max(aux[0], aux[1]) });
						continue chk;
					}
					g++;
					i = j + 1;
					for (int d = 0; d < M; d++)
						q[d] = cs[d][i];
				}
			}

			out.println(sols.size());
			Collections.sort(sols, (a, b) -> a[1] == b[1] ? a[0] - b[0] : a[1] - b[1]);
			for (int[] x : sols)
				out.printf("%d %d%n", x[1], x[0]);

		}

	}

	public static void main(String[] args) {

		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();

	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public int[] nextIntArray(int n) {
			int[] ret = new int[n];
			for (int i = 0; i < n; i++)
				ret[i] = nextInt();
			return ret;
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

	}

}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.PriorityQueue;

public class TennisGame {

	static class Solver {

		int N;
		int[] a, a1, a2, c1, c2;

		// returns the correct [s, t] pair or null if impossible
		int[] play(int t) {
			// System.out.println("t=" + t);
			int i, p, q, v, w;
			for (i = p = q = v = w = 0; i != N;) {
				// System.out.printf("i=%d p=%d q=%d v=%d w=%d a1[p+t]=%d a2[q+t]=%d%n", i, p,
				// q, v, w, a1[p + t],
				// a2[q + t]);
				int x = a1[p + t], y = a2[q + t];
				if (x == -1 && y == -1)
					return null;
				if (x == -1) {
					p = c1[y];
					q = c2[y];
					w++;
					i = y + 1;
				} else if (y == -1) {
					p = c1[x];
					q = c2[x];
					v++;
					i = x + 1;
				} else if (x < y) {
					p = c1[x];
					q = c2[x];
					v++;
					i = x + 1;
				} else {
					p = c1[y];
					q = c2[y];
					w++;
					i = y + 1;
				}
			}
			if (v == w)
				return null;
			if (v < w && a[N - 1] != 2)
				return null;
			if (v > w && a[N - 1] != 1)
				return null;
			return new int[] { Math.max(v, w), t };
		}

		void solve(FastScanner s, PrintWriter out) {
			N = s.nextInt();
			a = s.nextIntArray(N);
			a1 = new int[2 * N];
			a2 = new int[2 * N];
			Arrays.fill(a1, -1);
			Arrays.fill(a2, -1);
			int p = 0, q = 0;
			for (int i = 0; i < N; i++) {
				if (a[i] == 1)
					a1[++p] = i;
				else
					a2[++q] = i;
			}

			c1 = new int[N];
			c2 = new int[N];
			for (int i = 0; i < N; i++) {
				if (a[i] == 1) {
					c1[i] = 1;
				} else {
					c2[i] = 1;
				}
				if (i != 0) {
					c1[i] += c1[i - 1];
					c2[i] += c2[i - 1];
				}
			}

			PriorityQueue<int[]> ans = new PriorityQueue<>((a, b) -> a[0] == b[0] ? a[1] - b[1] : a[0] - b[0]);
			for (int t = 1; t <= N; t++) {
				int[] go = play(t);
				if (go != null)
					ans.add(go);
			}

			out.println(ans.size());
			while (!ans.isEmpty()) {
				int[] c = ans.poll();
				out.printf("%d %d%n", c[0], c[1]);
			}

		}

	}

	public static void main(String[] args) {
		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();
	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public long nextLong() {
			return Long.parseLong(next());
		}

		public double nextDouble() {
			return Double.parseDouble(next());
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

		// Jacob Garbage

		public int[] nextIntArray(int N) {
			int[] ret = new int[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextInt();
			return ret;
		}

		public long[] nextLongArray(int N) {
			long[] ret = new long[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextLong();
			return ret;
		}

		public int[][] next2DIntArray(int N, int M) {
			int[][] ret = new int[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextIntArray(M);
			return ret;
		}

		public double[] nextDoubleArray(int N) {
			double[] ret = new double[N];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDouble();
			return ret;
		}

		public double[][] next2DDoubleArray(int N, int M) {
			double[][] ret = new double[N][];
			for (int i = 0; i < N; i++)
				ret[i] = this.nextDoubleArray(M);
			return ret;
		}

	}

}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.InputMismatchException;

public class grouping {

	static class Solver {

		int N, M, a[], to[][], cs[][];

		void solve(FastScanner s, PrintWriter out) {

			N = s.nextInt();
			M = 2;
			a = s.nextIntArray(N);
			to = new int[M][N << 1];
			cs = new int[M][N << 1];

			for (int[] x : to)
				Arrays.fill(x, -1);
			for (int i = 0; i < N; i++) {
				int t = a[i] - 1;
				cs[t][i + 1]++;
				for (int j = 0; j < M; j++)
					cs[j][i + 1] += cs[j][i];
				to[t][cs[t][i + 1]] = i;
			}

			ArrayList<int[]> sols = new ArrayList<>();

			// i - left bound
			// j - variable right bound
			// g - groups made
			// q - how many of each used so far
			int i, j, g, q[];
			chk: for (int k = 1; k <= N; k++) {
				q = new int[M];
				i = g = 1;
				int[] aux = new int[2];
				while (i < N) {
					j = N;
					// d is breed of next leader
					for (int d = 0; d < M; d++) {
						if (to[d][q[d] + k] == -1)
							continue;
						j = Math.min(j, to[d][q[d] + k]);
					}
					if (j == N)
						continue chk;
					aux[a[j] - 1]++;
					if (j == N - 1) {
						if (aux[0] != aux[1])
							sols.add(new int[] { k, Math.max(aux[0], aux[1]) });
						continue chk;
					}
					g++;
					i = j + 1;
					for (int d = 0; d < M; d++)
						q[d] = cs[d][i];
				}
			}

			out.println(sols.size());
			for (int[] x : sols)
				out.printf("%d %d%n", x[0], x[1]);

		}

	}

	public static void main(String[] args) {

		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();

	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public int[] nextIntArray(int n) {
			int[] ret = new int[n];
			for (int i = 0; i < n; i++)
				ret[i] = nextInt();
			return ret;
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

	}

}


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.InputMismatchException;

public class grouping {

	static class Solver {

		int N, M, a[], to[][], cs[][];

		void solve(FastScanner s, PrintWriter out) {

			N = s.nextInt();
			M = 2;
			a = s.nextIntArray(N);
			to = new int[M][N << 1];
			cs = new int[M][N << 1];

			for (int[] x : to)
				Arrays.fill(x, -1);
			for (int i = 0; i < N; i++) {
				int t = a[i] - 1;
				cs[t][i + 1]++;
				for (int j = 0; j < M; j++)
					cs[j][i + 1] += cs[j][i];
				to[t][cs[t][i + 1]] = i;
			}

			ArrayList<int[]> sols = new ArrayList<>();

			// i - left bound
			// j - variable right bound
			// g - groups made
			// q - how many of each used so far
			int i, j, g, q[];
			chk: for (int k = 1; k <= N; k++) {
				q = new int[M];
				i = g = 1;
				int[] aux = new int[2];
				while (i < N) {
					j = N;
					// d is breed of next leader
					for (int d = 0; d < M; d++) {
						if (to[d][q[d] + k] == -1)
							continue;
						j = Math.min(j, to[d][q[d] + k]);
					}
					if (j == N)
						continue chk;
					aux[a[j] - 1]++;
					if (j == N - 1) {
						if (aux[0] != aux[1] && (a[j] - 1 == (aux[0] > aux[1] ? 0 : 1) || N == 1))
							sols.add(new int[] { k, Math.max(aux[0], aux[1]) });
						continue chk;
					}
					g++;
					i = j + 1;
					for (int d = 0; d < M; d++)
						q[d] = cs[d][i];
				}
			}

			out.println(sols.size());
			Collections.sort(sols, (a, b) -> a[1] == b[1] ? a[0] - b[0] : a[1] - b[1]);
			for (int[] x : sols)
				out.printf("%d %d%n", x[1], x[0]);

		}

	}

	public static void main(String[] args) {

		FastScanner s = new FastScanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		Solver solver = new Solver();
		solver.solve(s, out);

		out.close();

	}

	static class FastScanner {
		private InputStream stream;
		private byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public FastScanner(InputStream stream) {
			this.stream = stream;
		}

		int read() {
			if (numChars == -1)
				throw new InputMismatchException();
			if (curChar >= numChars) {
				curChar = 0;
				try {
					numChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (numChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		boolean isEndline(int c) {
			return c == '\n' || c == '\r' || c == -1;
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public int[] nextIntArray(int n) {
			int[] ret = new int[n];
			for (int i = 0; i < n; i++)
				ret[i] = nextInt();
			return ret;
		}

		public String next() {
			int c = read();
			while (isSpaceChar(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public String nextLine() {
			int c = read();
			while (isEndline(c))
				c = read();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = read();
			} while (!isEndline(c));
			return res.toString();
		}

	}

}


/**
 * ******* Created  on 15/1/20 6:32 PM*******
 */

import java.io.*;
import java.util.*;

public class D496 implements Runnable {

    private static final int MAX = (int) (1E5 + 5);
    private static final int MOD = (int) (1E9 + 7);
    private static final long Inf = (long) (1E14 + 10);

    private void solve() throws IOException {
        int n = reader.nextInt();
        ArrayList<Integer> ones = new ArrayList<>();
        ArrayList<Integer> twos = new ArrayList<>();
        int[] nextA = new int[n];
        int[] nextB = new int[n];
        for(int i=0;i<n;i++){
            nextA[i] = ones.size();
            nextB[i] = twos.size();
            if(reader.nextInt() == 1)
                ones.add(i);
            else
                twos.add(i);
        }
        List<Pair> ans = new ArrayList<>();
        ll: for(int i=1;i<=n;i++){
            int j1 =0, j2 =0, pos =0, lst =-1;
            while(pos !=n){
                int ptr1 = nextA[pos] +i-1;
                int ptr2 = nextB[pos] +i-1;
                int pos1 = ptr1 < ones.size() ? ones.get(ptr1):n;
                int pos2 = ptr2 < twos.size() ? twos.get(ptr2):n;
                if(pos1 ==n && pos2 ==n)
                    continue ll;
                if(pos1 < pos2){
                    ++j1;
                    pos = pos1 + 1;
                    lst = 1;
                }else{
                    ++j2;
                    pos = pos2 +1;
                    lst =2;
                }
            }
            if(lst == 1 && j1 > j2)
                ans.add(new Pair(j1,i));
            if(lst ==2 && j2 > j1)
                ans.add(new Pair(j2, i));
        }
        writer.println(ans.size());
        Collections.sort(ans);
        for(Pair p : ans)
            writer.println(p.s+" "+p.t);
    }
    static class Pair implements Comparable<Pair>{
        int s, t;
        Pair(int a,int b){
            s=a;t =b;
        }

        @Override
        public int compareTo(Pair o) {
            if(s != o.s)
                return s-o.s;
            return t-o.t;
        }
    }
    public static void main(String[] args) throws IOException {
        try (Input reader = new StandardInput(); PrintWriter writer = new PrintWriter(System.out)) {
            new D496().run();
        }
    }

    StandardInput reader;
    PrintWriter writer;

    @Override
    public void run() {
        try {
            reader = new StandardInput();
            writer = new PrintWriter(System.out);
            solve();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    interface Input extends Closeable {
        String next() throws IOException;

        default int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        default long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        default double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        default int[] readIntArray() throws IOException {
            return readIntArray(nextInt());
        }

        default int[] readIntArray(int size) throws IOException {
            int[] array = new int[size];
            for (int i = 0; i < array.length; i++) {
                array[i] = nextInt();
            }
            return array;
        }

        default long[] readLongArray(int size) throws IOException {
            long[] array = new long[size];
            for (int i = 0; i < array.length; i++) {
                array[i] = nextLong();
            }
            return array;
        }
    }

    private static class StandardInput implements Input {
        private final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        private StringTokenizer stringTokenizer;

        @Override
        public void close() throws IOException {
            reader.close();
        }

        @Override
        public String next() throws IOException {
            if (stringTokenizer == null || !stringTokenizer.hasMoreTokens()) {
                stringTokenizer = new StringTokenizer(reader.readLine());
            }
            return stringTokenizer.nextToken();
        }
    }
}


import java.util.Scanner;

public class TaskFour {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];

        int[] first = new int[n + 1];
        int[] second = new int[n + 1];
        int[] firstFast = new int[n * 2];
        int[] secondFast = new int[n * 2];
        for (int i = 0; i < firstFast.length; i++) {
            firstFast[i] = -1;
            secondFast[i] = -1;
        }
        for (int i = 0; i < a.length; i++) {
            a[i] = sc.nextInt();
            if (1 == a[i]) {
                first[i + 1] = first[i] + 1;
                firstFast[first[i + 1]] = i + 1;
                second[i + 1] = second[i];
            } else {
                first[i + 1] = first[i];
                second[i + 1] = second[i] + 1;
                secondFast[second[i + 1]] = i + 1;
            }
        }
        int count = 0;
        int[] t = new int[n];
        int[] s = new int[n];
        int last = 0;
        for (int t_ = 1; t_ <= n; t_++) {
            int s1 = 0;
            int s2 = 0;
            last = 0;
            int next1 = firstFast[first[last] + t_];
            int next2 = secondFast[second[last] + t_];
            while (-1 != next1 || -1 != next2) {
                if ((next1 < next2 || -1 == next2) && -1 != next1) {
                    s1++;
                    last = next1;
                } else {
                    s2++;
                    last = next2;
                }
                if (n <= last) {
                    break;
                }
                next1 = firstFast[first[last] + t_];
                next2 = secondFast[second[last] + t_];
            }
            if (last == n && s1 != s2) {
                if ((s1 > s2 && next1 == last) || (s2 > s1 && next2 == last)) {
                    t[count] = t_;
                    s[count] = Math.max(s1, s2);
                    count++;
                }
            }
        }
        System.out.println(count);
        for (int i = count - 1; i > -1; i--) {
            System.out.println(s[i] + " " + t[i]);
        }
    }
}


import java.util.Scanner;

public class TaskFour {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];

        int[] first = new int[n + 1];
        int[] second = new int[n + 1];
        int[] firstFast = new int[n * 2];
        int[] secondFast = new int[n * 2];
        for (int i = 0; i < firstFast.length; i++) {
            firstFast[i] = -1;
            secondFast[i] = -1;
        }
        for (int i = 0; i < a.length; i++) {
            a[i] = sc.nextInt();
            if (1 == a[i]) {
                first[i + 1] = first[i] + 1;
                firstFast[first[i + 1]] = i + 1;
                second[i + 1] = second[i];
            } else {
                first[i + 1] = first[i];
                second[i + 1] = second[i] + 1;
                secondFast[second[i + 1]] = i + 1;
            }
        }
        int count = 0;
        int[] t = new int[n];
        int[] s = new int[n];
        int last = 0;
        for (int t_ = 1; t_ <= n; t_++) {
            int s1 = 0;
            int s2 = 0;
            last = 0;
            int next1 = firstFast[first[last] + t_];
            int next2 = secondFast[second[last] + t_];
            while (-1 != next1 || -1 != next2) {
                if ((next1 < next2 || -1 == next2) && -1 != next1) {
                    s1++;
                    last = next1;
                } else {
                    s2++;
                    last = next2;
                }
                if (n <= last) {
                    break;
                }
                next1 = firstFast[first[last] + t_];
                next2 = secondFast[second[last] + t_];
            }
            if (last == n && s1 != s2) {
                if ((s1 > s2 && next1 == last) || (s2 > s1 && next2 == last)) {
                    t[count] = t_;
                    s[count] = Math.max(s1, s2);
                    count++;
                }
            }
        }
        System.out.println(count);
        //sort
        for (int i = 0; i < count; i++) {
            for (int j = 1; j < count; j++) {
                if (s[j-1] > s[j]
                        ||(s[j-1] == s[j] && t[j-1] > t[j])){
                    int tmp;
                    tmp = s[j-1];
                    s[j-1] = s[j];
                    s[j] = tmp;
                    tmp = t[j-1];
                    t[j-1] = t[j];
                    t[j] = tmp;
                }
            }
        }
        for (int j = 0; j < count; j++) {
            System.out.println(s[j] + " " + t[j]);
        }
    }
}


import java.util.Scanner;

public class TaskFour {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];

        int[] first = new int[n + 1];
        int[] second = new int[n + 1];
        int[] firstFast = new int[n * 2];
        int[] secondFast = new int[n * 2];
        for (int i = 0; i < firstFast.length; i++) {
            firstFast[i] = -1;
            secondFast[i] = -1;
        }
        for (int i = 0; i < a.length; i++) {
            a[i] = sc.nextInt();
            if (1 == a[i]) {
                first[i + 1] = first[i] + 1;
                firstFast[first[i + 1]] = i + 1;
                second[i + 1] = second[i];
            } else {
                first[i + 1] = first[i];
                second[i + 1] = second[i] + 1;
                secondFast[second[i + 1]] = i + 1;
            }
        }
        int count = 0;
        int[] t = new int[n];
        int[] s = new int[n];
        int last = 0;
        for (int t_ = 1; t_ <= n; t_++) {
            int s1 = 0;
            int s2 = 0;
            last = 0;
            int next1 = firstFast[first[last] + t_];
            int next2 = secondFast[second[last] + t_];
            while (-1 != next1 || -1 != next2) {
                if ((next1 < next2 || -1 == next2) && -1 != next1) {
                    s1++;
                    last = next1;
                } else {
                    s2++;
                    last = next2;
                }
                if (n <= last) {
                    break;
                }
                next1 = firstFast[first[last] + t_];
                next2 = secondFast[second[last] + t_];
            }
            if (last == n && s1 != s2) {
                t[count] = t_;
                s[count] = Math.max(s1, s2);
                count++;
            }
        }
        System.out.println(count);
        for (int i = count-1; i > -1; i--) {
            System.out.println(s[i] + " " + t[i]);
        }
    }
}


import java.util.Scanner;

public class TaskFour {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];

        int[] first = new int[n + 1];
        int[] second = new int[n + 1];
        int[] firstFast = new int[n * 2];
        int[] secondFast = new int[n * 2];
        for (int i = 0; i < firstFast.length; i++) {
            firstFast[i] = -1;
            secondFast[i] = -1;
        }
        for (int i = 0; i < a.length; i++) {
            a[i] = sc.nextInt();
            if (1 == a[i]) {
                first[i + 1] = first[i] + 1;
                firstFast[first[i + 1]] = i + 1;
                second[i + 1] = second[i];
            } else {
                first[i + 1] = first[i];
                second[i + 1] = second[i] + 1;
                secondFast[second[i + 1]] = i + 1;
            }
        }
        int count = 0;
        int[] t = new int[n];
        int[] s = new int[n];
        int last = 0;
        for (int t_ = 1; t_ <= n; t_++) {
            int s1 = 0;
            int s2 = 0;
            last = 0;
            int next1 = firstFast[first[last] + t_];
            int next2 = secondFast[second[last] + t_];
            while (-1 != next1 || -1 != next2) {
                if ((next1 < next2 || -1 == next2) && -1 != next1) {
                    s1++;
                    last = next1;
                } else {
                    s2++;
                    last = next2;
                }
                if (n <= last) {
                    break;
                }
                next1 = firstFast[first[last] + t_];
                next2 = secondFast[second[last] + t_];
            }
            if (last == n && s1 != s2) {
                t[count] = t_;
                s[count] = Math.max(s1, s2);
                count++;
            }
        }
        System.out.println(count);
        for (int i = 0; i < count; i++) {
            System.out.println(s[i] + " " + t[i]);
        }
    }
}