#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

// 各パーツの連結情報を表すテーブル
int con[12][4] = {
	{0, 0, 0, 0},
	{0, 1, 0, 1},
	{1, 0, 1, 0},
	{1, 1, 0, 0},
	{1, 0, 0, 1},
	{0, 0, 1, 1},
	{0, 1, 1, 0},
	{1, 1, 0, 1},
	{1, 0, 1, 1},
	{0, 1, 1, 1},
	{1, 1, 1, 0},
	{1, 1, 1, 1}
};

// (R > C)の場合に各パーツを転置して(R < C)に変換するためのテーブル
int chg[] = {0, 2, 1, 5, 4, 3, 6, 8, 7, 10, 9, 11};

// 1列分の連結状況の更新用テーブル(R=3専用)
// 0bit : 置いたピースと1つ前のピースが連結
// 1bit : 置いたピースと1列前(3つ前)のピースが連結
int next[10][4] = {
	{-1, -1, 4, 6}, // 0: 3つ前だけ(1,1)と連結
	    //   x  0:   x   1:   b  2:   x  3:   o
		// o ?     x x      o b     o o     o o
		// x       x        x       x       x
	{-1, -1, 5, 9}, // 1: 3つ前だけ(1,1)と連結 + 1つ前と2つ前が連結 
	    //   b  0:   b   1:   b  2:   b  3:   o
		// o ?     o x      o b     o o     o o
		// b       b        b       b       o
	{0, 1, 0, 1}, // 2: 2つ前だけ(1,1)と連結
		//   x  0:   x   1:   b  2:   x  3:   b
		// x ?     x x      x b     b b     b b
		// o       o        o       o       o
	{0, 1, 1, 1}, // 3: 2つ前だけ(1,1)と連結 + 1つ前と3つ前が連結
		//   b  0:   b   1:   b  2:   b  3:   b
		// b ?     b x      b b     b b     b b
		// o       o        o       o       o
	{2, 6, 2, 6}, // 4: 1つ前だけ(1,1)と連結
		//   o  0:   o   1:   o  2:   o  3:   o
		// x ?     x x      x o     b b     o o
		// x       x        x       x       x
	{2, 6, 3, 9}, // 5: 1つ前だけ(1,1)と連結 + 2つ前と3つ前が連結
		//   o  0:   o   1:   o  2:   o  3:   o
		// b ?     b x      b o     b b     o o
		// b       b        b       b       o
	{8, 9, 8, 9}, // 6: 1つ前と2つ前が(1,1)と連結
		//   o  0:   o   1:   o  2:   o  3:   o
		// x ?     x x      x o     b b     o o
		// o       o        o       o       o
	{2, 6, 6, 6}, // 7: 1つ前と3つ前が(1,1)と連結
		//   o  0:   o   1:   o  2:   o  3:   o
		// o ?     o x      o o     o o     o o
		// x       x        x       x       x
	{0, 1, 7, 9}, // 8: 2つ前と3つ前が(1,1)と連結
		//   x  0:   x   1:   b  2:   x  3:   o
		// o ?     o x      o b     o o     o o
		// o       o        o       o       o
	{8, 9, 9, 9}, // 9: 3つ前まですべて(1,1)と連結
		//   o  0:   o   1:   o  2:   o  3:   o
		// o ?     o x      o o     o o     o o
		// o       o        o       o       o
};

// [使用済みピース] : 最大2^15通り
// [最後に置いたピースから下方向に道が伸びてるか] : 2通り
// [置いた最左列の各ピースから右に道が伸びてるか] : 最大2^min(R,C) = 2^3通り
// [スタート地点のピースからの連結情報] : min(R,C) = 3 の場合で10通り
long long dp[1<<15][2][8][10];

int bitCount(int b){
	int res = 0;
	for(int t=b;t;t&=(t-1)) res++;
	return res;
}

int main(){
	int R, C;
	int visit[12];
	while(cin >> R >> C){
		vector<int> vi;
		for(int i=0;i<12;i++){
			int n; cin >> n;
			for(int j=0;j<n;j++) vi.push_back(i);
		}

		if(R > C){
			// R < C (R ≦ 3) になるようにピースを変換
			swap(R, C);
			for(int i=0;i<vi.size();i++) vi[i] = chg[vi[i]];
		}
		long long res = 0;

		memset(dp, 0, sizeof(dp));
		vector<int> mask(vi.size(), 0);
		for(int i=0;i<vi.size();i++){
			for(int j=0;j<i;j++)
				if(vi[i] == vi[j]) mask[j] |= 1<<i; // 重複カウント排除用マスク
		}
		for(int i=0;i<vi.size();i++){
			if(mask[i] != 0) continue;
			bool downPipe  = (R > 1 && con[vi[i]][3]);
			bool rightPipe = con[vi[i]][0];
			if(!downPipe && !rightPipe) continue;
			dp[1<<i][downPipe][rightPipe][R==3 ? 4 : 1] = 1;
		}
		int type[] = {0, 2, 4, 10}; // type[i] : min(R, C) = i の時の連結情報の種類数
		for(int i=0;i<(1<<vi.size());++i){
			int bits = bitCount(i);
			if(bits >= R*C) continue;
			for(int down=0;down<2;down++){
				for(int right=0;right<(1<<R);right++){
					if(down == 0 && right == 0) continue; // 置いたピースにつなげられる経路がない
					for(int connect=0;connect<type[R];connect++){
						if(dp[i][down][right][connect] == 0) continue; // この状態に至る経路がない
						for(int j=0;j<vi.size();j++){
							if(i&(1<<j)) continue;
							if((i&mask[j]) != mask[j]) continue; // 同じ種類のピースはindexが若いものから使う
							bool ndown = bits%R != R-1 && con[vi[j]][3];
							int nright = (2*right)%(1<<R) + con[vi[j]][0];
							int nconnect;
							if(R < 3){
								nconnect = (2*connect)%(1<<R);
								if((right&(1<<(R-1))) && con[vi[j]][2]){
									if(connect&(1<<(R-1))){
										nconnect |= 1;
										if(down && con[vi[j]][1]) nconnect |= (1<<(R-1));
									}
								}
								if(down && con[vi[j]][1] && (connect&1))
								nconnect |= 1;
								if(nconnect == 0) continue; // 最左ピースがどれもスタート地点のピースと連結でない
								if((nconnect&1) && bits+1 == R*C) // スタート地点のピースとゴール地点のピースが連結
									res += dp[i][down][right][connect]; 
							}
							else if(R == 3){
								int piece = 0;
								if(down && con[vi[j]][1]) piece |= 1;
								if((right&(1<<(R-1))) && con[vi[j]][2]) piece |= 2;
								nconnect = next[connect][piece];
								if(nconnect == -1) continue; // 最左ピースがどれもスタート地点のピースと連結でない
								if((0x000002F0 & (1<<nconnect)) && bits+1 == R*C) // スタート地点のピースとゴール地点のピースが連結
									res += dp[i][down][right][connect];
							}
							dp[i|(1<<j)][ndown][nright][nconnect] += dp[i][down][right][connect];
						}
					}
				}
			}
		}
		cout << res << endl;
	}
}

Measured memory_bytes: 42176