#include <iostream>
#include <vector>

using namespace std;

#define PROBLEM "G"

#define pb push_back
#define sz(c) (int) (c).size()

#define MAXN 10
#define MAXM 10
#define MAXK 25
#define MAXW 20
#define MAXH 20
#define LIM 10000

struct t_poly {
	int w, h, k;
	char a[MAXW][MAXH];
};

t_poly rotate(t_poly a) {
	t_poly res;
	res.h = a.w, res.w = a.h;
	for (int r = 0; r < res.h; r++)
		for (int c = 0; c < res.w; c++)
			res.a[r][c] = a.a[a.h - c - 1][r];
	return res;
}

int findk(t_poly p) {
	int i = 0;
	while (p.a[0][i] == '.') i++;
	return i;
}

bool same(t_poly a, t_poly b) {
	if (a.w != b.w || a.h != b.h) return false;
	for (int r = 0; r < a.h; r++) {
		for (int c = 0; c < a.w; c++) {
			if (a.a[r][c] == '.' && b.a[r][c] != '.') return false;
			if (b.a[r][c] == '.' && a.a[r][c] != '.') return false;
		}
	}
	return true;
}

bool same(vector < t_poly > a, vector < t_poly > b) {
	for (int i = 0; i < sz(a); i++) {
		for (int j = 0; j < sz(b); j++) {
			if (same(a[i], b[j])) return true;
		}
	}
	return false;
}

t_poly p[MAXK];
vector < t_poly > P[MAXK];
int tp[MAXK], tpc[MAXK], tpci[MAXK];
int C[MAXK][MAXK];
long long F[MAXK];
int N, M, K;
char a[MAXN][MAXM];
int res = 0;

void print(t_poly *p) {
	cout << p -> h << "x" << p -> w << endl;
	for (int r = 0; r < p -> h; r++) {
		for (int c = 0; c < p -> w; c++) {
			putchar(p -> a[r][c]);
		}
		putchar('\n');
	}
}

void printa() {
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < M; j++) 
			cout << a[i][j];
		cout << endl;	
	}
	cout << endl;
}

bool put(t_poly p, int x, int y) {
	for (int r = 0; r < p.h; r++)
		for (int c = 0; c < p.w; c++) {
			if (x + r >= N || y + c - p.k < 0 || y + c - p.k >= M || (p.a[r][c] != '.' && a[x + r][y + c - p.k] != '.'))
				return false;
		}
   for (int r = 0; r < p.h; r++)
		for (int c = 0; c < p.w; c++) {
			if (p.a[r][c] != '.') a[x + r][y + c - p.k] = p.a[r][c];
		}
	return true;
}

bool take(t_poly p, int x, int y) {
   for (int r = 0; r < p.h; r++)
		for (int c = 0; c < p.w; c++) {
			if (p.a[r][c] != '.') a[x + r][y + c - p.k] = '.';
		}
	return true;
}

void solve(int r, int c) {
	while (r < N && a[r][c] != '.') {
		c++;
		if (c == M) r++, c = 0;
	}
	if (r == N) {
//		printa();
		long long t = 1;
		for (int i = 0; i < K; i++)
			if (tpci[i] != 0) t *= C[tpci[i]][tpc[i]] * F[tpci[i] - tpc[i]];
		if (t > LIM) res = LIM + 1; else res += t;
		return;
	}
//	printa();
//	cout << r << " " << c << endl;
//	for (int i = 0; i < K; i++) cout << tpc[tp[i]] << " "; cout << endl;
	for (int i = 0; i < K; i++) {
		if (tp[i] == i && tpc[tp[i]]) {
			tpc[tp[i]]--;
			for (int j = 0; j < sz(P[i]); j++)
				if (put(P[i][j], r, c)) {
					solve(r, c);
					if (res > LIM) return;
					take(P[i][j], r, c);
				}
			tpc[tp[i]]++;
		}
	}
}

int main() {
	freopen(PROBLEM ".in", "r", stdin);
	freopen(PROBLEM ".out", "w", stdout);
	scanf("%d %d\n", &N, &M);
	scanf("%d\n", &K);
	for (int i = 0; i < K; i++) {
		scanf("%d %d\n", &p[i].h, &p[i].w);
		for (int r = 0; r < p[i].h; r++) {
			gets(p[i].a[r]);
		}
	}

	for (int i = 0; i < K; i++) {
		P[i].pb(p[i]);
		for (int j = 0; j < 3; j++) {
			t_poly tmp = rotate(P[i][sz(P[i]) - 1]);
			bool was = false;
			for (int k = 0; k < sz(P[i]); k++)
				if (same(P[i][k], tmp)) {
					was = true;
					break;
				}
			if (!was) P[i].pb(tmp);
		}
	}

	for (int i = 0; i < K; i++) {
		for (int j = 0; j < K; j++) {
			if (same(P[i], P[j])) {
				tp[i] = j;
				break;
			}
		}
	}

	for (int i = 0; i < K; i++) tpc[tp[i]]++;
	for (int i = 0; i < K; i++) tpci[i] = tpc[i];

	for (int i = 0; i < K; i++) {
		for (int j = 0; j < sz(P[i]); j++)
			P[i][j].k = findk(P[i][j]);
	}


	C[0][0] = 1;
	for (int i = 1; i <= K; i++) {
		for (int j = 0; j <= i; j++) {
			C[i][j] = C[i - 1][j];
			if (j) C[i][j] += C[i - 1][j - 1];
		}
	}

	F[0] = 1;
	for (int i = 1; i <= K; i++) F[i] = i * F[i - 1];
   

	memset(a, '.', sizeof(a));
	solve(0, 0);

	if (res > LIM)
		cout << "TOO MANY" << endl;
	else
		cout << res << endl;

	return 0;
}
