Problem:
Problem I:
Tatami
A tatami mat, a Japanese traditional floor cover, has a rectangular form with aspect ratio 1:2. When
spreading tatami mats on a floor, it is prohibited to make a cross with the border of the tatami mats,
because it is believed to bring bad luck.
Your task is to write a program that reports how many possible ways to spread tatami mats of the same
size on a floor of given height and width.
Input
The input consists of multiple datasets. Each dataset cosists of a line which contains two integers
H
and
W
in this order, separated with a single
space.
H
and
W
are the height and the width of the floor respectively. The length of the shorter edge of a
tatami mat is regarded as a unit length.
You may assume 0 <
H
,
W
≤ 20.
The last dataset is followed by a line containing two zeros. This line is not a part of any dataset and should not be processed.
Output
For each dataset, print the number of possible ways to spread tatami mats in one line.
Sample Input
3 4
4 4
0 0
Output for the Sample Input
4
2

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

using VS = vector<string>;    using LL = long long;
using VI = vector<int>;       using VVI = vector<VI>;
using PII = pair<int, int>;   using PLL = pair<LL, LL>;
using VL = vector<LL>;        using VVL = vector<VL>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)
#define FORR(i, s, e) for (int(i) = (s); (i) > (e); (i)--)
#define debug(x) cerr << #x << ": " << x << endl
const int INF = 1e9;                          const LL LINF = 1e16;
const LL MOD = 1000000007;                    const double PI = acos(-1.0);
int DX[8] = { 0, 0, 1, -1, 1, 1, -1, -1 };    int DY[8] = { 1, -1, 0, 0, 1, -1, 1, -1 };

/* -----  2017/12/11  Problem: AOJ 2163 / Link: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2163  ----- */
/* ------問題------



-----問題ここまで----- */
/* -----解説等-----



----解説ここまで---- */
class DominoTiling
{
public:

	LL dp[2][1 << 14];
	long long count(vector<string>& grid) {


		LL H = SZ(grid); LL W = SZ(grid[0]);
		dp[0][0] = 1LL;
		for (int i = H - 1; i >= 0; i--) {
			for (int j = W - 1; j >= 0; j--) {
				FOR(used, 0, 1 << W) {
					if (((used >> j) & 1) || grid[i][j] == 'X') {
						dp[1][used] = dp[0][used & (~(1 << j))];
					}
					else {
						LL res = 0;
						if (j + 1 < W && !(used >> (j + 1) & 1) && (grid[i][j + 1] != 'X')) {
							res += dp[0][used | 1 << (j + 1)];
						}
						if (i + 1 < H && (grid[i + 1][j] != 'X')) {
							res += dp[0][used | 1 << j];
						}
						dp[1][used] = res;
					}
				}
				FOR(i, 0, 1LL << W) {//swap
					dp[0][i] = dp[1][i];
					dp[1][i] = 0;
				}
			}
		}

		return dp[0][0];
	}
};

LL ans;
LL H, W;
int masu[20][20];

bool have_same(int y, int x) {
	int b = masu[y][x - 1];
	int u = masu[y - 1][x];	int l = masu[y - 1][x - 1];
	return(b == u || b == l || u == l);
}

void f(int val, int y, int x) {
	if (y == H) {
		ans++; return;
	}
	else if (x == W) {
		f(val, y + 1, 0);
		return;
	}
	else if (masu[y][x] != -1) {
		f(val, y, x + 1);
		return;
	}
	else if (masu[y][x] == -1) {

		if (y + 1 < H && masu[y + 1][x] == -1) { //下に詰める
			masu[y][x] = val;
			masu[y + 1][x] = val;

			if (y > 0 && x > 0) {//上をチェックできるとき
				if (have_same(y, x)) f(val + 1, y, x + 1);
			}
			else f(val + 1, y, x + 1);

			masu[y][x] = -1;
			masu[y + 1][x] = -1;
		}

		if (x + 1 < W && masu[y][x + 1] == -1) { //右に詰める
			masu[y][x] = val;
			masu[y][x + 1] = val;

			if (y > 0 && x > 0) {//上をチェックできるとき
				if (have_same(y, x)) f(val + 1, y, x + 1);
			}
			else f(val + 1, y, x + 1);

			masu[y][x] = -1;
			masu[y][x + 1] = -1;
		}

	}
}

int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);

	while (cin >> H >> W, H || W) {
		ans = 0;
		fill(*masu, *masu + 20 * 20, -1);

		f(0, 0, 0);

		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3468
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

int memo[21][21];
int h, w, ans;
vector<string> s(20, string(20, '.'));

bool can(int i, int j) {
    if(i == 0 or j == w) return 1;
    if(s[i - 1][j - 1] == '<' or s[i - 1][j - 1] == '^') return 1;
    if(s[i - 1][j] == '^' or s[i - 1][j] == '>') return 1;
    return 0;
}
void dfs(int i, int j) {
    if(j == w) {
        i ++;
        j = 0;
    }
    if(i == h) {
        ans ++;
        // rep(y, h) cout << s[y].substr(0, w) << endl;
        return;
    }
    while(s[i][j] != '.') {
        j ++;
        if(j == w) {
            i ++;
            j = 0;
        }
        if(i == h) {
            ans ++;
            // rep(y, h) cout << s[y].substr(0, w) << endl;
            return;
        }
    }
    if(j != w - 1 and s[i][j + 1] == '.' and can(i, j + 2)) {
        s[i][j] = '<';
        s[i][j + 1] = '>';
        dfs(i, j + 2);
        s[i][j] = s[i][j + 1] = '.';
    }
    if(i != h - 1 and (j == w - 1 or s[i][j + 1] != '.' or can(i, j + 1))) {
        s[i][j] = '^';
        s[i + 1][j] = 'v';
        dfs(i, j + 1);
        s[i][j] = s[i + 1][j] = '.';
    }
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    // 全探索できるんじゃね？
    memset(memo, -1, sizeof(memo));
    cin >> h >> w;
    while(h) {
        if(memo[h][w] != -1) {
            cout << memo[h][w] << '\n';
            cin >> h >> w;
            continue;
        }
        ans = 0;
        dfs(0, 0);
        memo[h][w] = ans;
        cout << ans << '\n';
        cin >> h >> w;
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3464
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int N, M, K;
vector<vector<int>> A;

bool Check(int X, int Y) {
    if (X+1 == N || Y+1 == M) return true;
    rep(i,0,2) rep(j,0,2) if (A[X+i][Y+j] == -1) return true;
    rep(i,0,2) if (A[X+i][Y] == A[X+i][Y+1]) return true;
    rep(j,0,2) if (A[X][Y+j] == A[X+1][Y+j]) return true;
    return false;
}

bool ALLCheck() {
    rep(i,0,N-1) {
        rep(j,0,M-1) {
            if (!Check(i,j)) return false;
        }
    }
    return true;
}

ll DFS(int Dep) {
    if (Dep == K) return 1;
    int X, Y;
    rep(i,0,N) {
        rep(j,0,M) {
            if (A[i][j] == -1) {
                X = i, Y = j;
                goto Next;
            }
        }
    }
    Next:
    ll Ret = 0;
    if (X+1 < N && A[X+1][Y] == -1) {
        A[X][Y] = A[X+1][Y] = Dep;
        if (ALLCheck()) Ret += DFS(Dep+1);
        A[X][Y] = A[X+1][Y] = -1;
    }
    if (Y+1 < M && A[X][Y+1] == -1) {
        A[X][Y] = A[X][Y+1] = Dep;
        if (ALLCheck()) Ret += DFS(Dep+1);
        A[X][Y] = A[X][Y+1] = -1;
    }
    return Ret;
}

int main() {
while(1) {
    cin >> N >> M;
    if (N == 0) return 0;
    if ((N*M)%2 == 1) {
        cout << 0 << endl;
        continue;
    }
    K = (N*M)/2;
    A.assign(N,vector<int>(M,-1));
    cout << DFS(0) << endl;
}
}
accuracy: 1
time_ms: 3950
memory_kb: 3384
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll=long long;


int H,W,an=0;
pair<int,int> nex(pair<int,int> p){
    if(p.second==W-1)return {p.first+1,0};
    else return {p.first,p.second+1};
}
void dfs(pair<int,int> p,int c,vector<vector<int>> &V){
    auto [h,w]=p;
    if(h==H){
        an++;
        return;
    }
    else if(V[h][w]!=-1)dfs(nex(p),c,V);
    else{
        if(h>0&&w>0){
            if(V[h-1][w-1]!=V[h][w-1]&&V[h-1][w-1]!=V[h-1][w])return;
        }
        if(h+1<H&&V[h+1][w]==-1){
            V[h][w]=V[h+1][w]=c;
            dfs(nex(p),c+1,V);
            V[h][w]=V[h+1][w]=-1;
        }
        if(w+1<W&&V[h][w+1]==-1){
            V[h][w]=V[h][w+1]=c;
            dfs(nex(p),c+1,V);
            V[h][w]=V[h][w+1]=-1;
        }
    }
}

int main() {
    while(cin>>H>>W,H+W!=0){
        vector<vector<int>> V(H,vector<int>(W,-1));
        an=0;
        dfs({0,0},0,V);
        cout<<an<<endl;
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3384
final_rank: 10

code_snippet: #include <bits/stdc++.h>

#include <limits>
#include <type_traits>

namespace suisen {
// ! utility
template <typename ...Types>
using constraints_t = std::enable_if_t<std::conjunction_v<Types...>, std::nullptr_t>;
template <bool cond_v, typename Then, typename OrElse>
constexpr decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) {
    if constexpr (cond_v) {
        return std::forward<Then>(then);
    } else {
        return std::forward<OrElse>(or_else);
    }
}

// ! function
template <typename ReturnType, typename Callable, typename ...Args>
using is_same_as_invoke_result = std::is_same<std::invoke_result_t<Callable, Args...>, ReturnType>;
template <typename F, typename T>
using is_uni_op = is_same_as_invoke_result<T, F, T>;
template <typename F, typename T>
using is_bin_op = is_same_as_invoke_result<T, F, T, T>;

template <typename Comparator, typename T>
using is_comparator = std::is_same<std::invoke_result_t<Comparator, T, T>, bool>;

// ! integral
template <typename T, typename = constraints_t<std::is_integral<T>>>
constexpr int bit_num = std::numeric_limits<std::make_unsigned_t<T>>::digits;
template <typename T, unsigned int n>
struct is_nbit { static constexpr bool value = bit_num<T> == n; };
template <typename T, unsigned int n>
static constexpr bool is_nbit_v = is_nbit<T, n>::value;

// ?
template <typename T>
struct safely_multipliable {};
template <>
struct safely_multipliable<int> { using type = long long; };
template <>
struct safely_multipliable<long long> { using type = __int128_t; };
template <>
struct safely_multipliable<unsigned int> { using type = unsigned long long; };
template <>
struct safely_multipliable<unsigned long int> { using type = __uint128_t; };
template <>
struct safely_multipliable<unsigned long long> { using type = __uint128_t; };
template <>
struct safely_multipliable<float> { using type = float; };
template <>
struct safely_multipliable<double> { using type = double; };
template <>
struct safely_multipliable<long double> { using type = long double; };
template <typename T>
using safely_multipliable_t = typename safely_multipliable<T>::type;

} // namespace suisen

// ! type aliases
using i128 = __int128_t;
using u128 = __uint128_t;

template <typename T>
using pq_greater = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T, typename U>
using umap = std::unordered_map<T, U>;

// ! macros (capital: internal macro)
#define OVERLOAD2(_1,_2,name,...) name
#define OVERLOAD3(_1,_2,_3,name,...) name
#define OVERLOAD4(_1,_2,_3,_4,name,...) name

#define REP4(i,l,r,s)  for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l);i<(r);i+=(s))
#define REP3(i,l,r)    REP4(i,l,r,1)
#define REP2(i,n)      REP3(i,0,n)
#define REPINF3(i,l,s) for(std::remove_reference_t<std::remove_const_t<decltype(l)>>i=(l);;i+=(s))
#define REPINF2(i,l)   REPINF3(i,l,1)
#define REPINF1(i)     REPINF2(i,0)
#define RREP4(i,l,r,s) for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l)+fld((r)-(l)-1,s)*(s);i>=(l);i-=(s))
#define RREP3(i,l,r)   RREP4(i,l,r,1)
#define RREP2(i,n)     RREP3(i,0,n)

#define rep(...)    OVERLOAD4(__VA_ARGS__, REP4   , REP3   , REP2   )(__VA_ARGS__)
#define rrep(...)   OVERLOAD4(__VA_ARGS__, RREP4  , RREP3  , RREP2  )(__VA_ARGS__)
#define repinf(...) OVERLOAD3(__VA_ARGS__, REPINF3, REPINF2, REPINF1)(__VA_ARGS__)

#define CAT_I(a, b) a##b
#define CAT(a, b) CAT_I(a, b)
#define UNIQVAR(tag) CAT(tag, __LINE__)
#define loop(n) for (std::remove_reference_t<std::remove_const_t<decltype(n)>> UNIQVAR(loop_variable) = n; UNIQVAR(loop_variable) --> 0;)

#define all(iterable) std::begin(iterable), std::end(iterable)
#define input(type, ...) type __VA_ARGS__; read(__VA_ARGS__)

#ifdef LOCAL
#  define debug(...) debug_internal(#__VA_ARGS__, __VA_ARGS__)

template <class T, class... Args>
void debug_internal(const char* s, T&& first, Args&&... args) {
    constexpr const char* prefix = "[\033[32mDEBUG\033[m] ";
    constexpr const char* open_brakets = sizeof...(args) == 0 ? "" : "(";
    constexpr const char* close_brakets = sizeof...(args) == 0 ? "" : ")";
    std::cerr << prefix << open_brakets << s << close_brakets << ": " << open_brakets << std::forward<T>(first);
    ((std::cerr << ", " << std::forward<Args>(args)), ...);
    std::cerr << close_brakets << "\n";
}

#else
#  define debug(...) void(0)
#endif

// ! I/O utilities

// pair
template <typename T, typename U>
std::ostream& operator<<(std::ostream& out, const std::pair<T, U> &a) {
    return out << a.first << ' ' << a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::ostream& operator<<(std::ostream& out, const std::tuple<Args...> &a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return out;
    } else {
        out << std::get<N>(a);
        if constexpr (N + 1 < std::tuple_size_v<std::tuple<Args...>>) {
            out << ' ';
        }
        return operator<<<N + 1>(out, a);
    }
}
// vector
template <typename T>
std::ostream& operator<<(std::ostream& out, const std::vector<T> &a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
// array
template <typename T, size_t N>
std::ostream& operator<<(std::ostream& out, const std::array<T, N> &a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
inline void print() { std::cout << '\n'; }
template <typename Head, typename... Tail>
inline void print(const Head &head, const Tail &...tails) {
    std::cout << head;
    if (sizeof...(tails)) std::cout << ' ';
    print(tails...);
}
template <typename Iterable>
auto print_all(const Iterable& v, std::string sep = " ", std::string end = "\n") -> decltype(std::cout << *v.begin(), void()) {
    for (auto it = v.begin(); it != v.end();) {
        std::cout << *it;
        if (++it != v.end()) std::cout << sep;
    }
    std::cout << end;
}

// pair
template <typename T, typename U>
std::istream& operator>>(std::istream& in, std::pair<T, U> &a) {
    return in >> a.first >> a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::istream& operator>>(std::istream& in, std::tuple<Args...> &a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return in;
    } else {
        return operator>><N + 1>(in >> std::get<N>(a), a);
    }
}
// vector
template <typename T>
std::istream& operator>>(std::istream& in, std::vector<T> &a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
// array
template <typename T, size_t N>
std::istream& operator>>(std::istream& in, std::array<T, N> &a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
template <typename ...Args>
void read(Args &...args) {
    ( std::cin >> ... >> args );
}

// ! integral utilities

// Returns pow(-1, n)
template <typename T>
constexpr inline int pow_m1(T n) {
    return -(n & 1) | 1;
}
// Returns pow(-1, n)
template <>
constexpr inline int pow_m1<bool>(bool n) {
    return -int(n) | 1;
}

// Returns floor(x / y)
template <typename T>
constexpr inline T fld(const T x, const T y) {
    return (x ^ y) >= 0 ? x / y : (x - (y + pow_m1(y >= 0))) / y;
}
template <typename T>
constexpr inline T cld(const T x, const T y) {
    return (x ^ y) <= 0 ? x / y : (x + (y + pow_m1(y >= 0))) / y;
}

template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int popcount(const T x) { return __builtin_popcount(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int popcount(const T x) { return __builtin_popcount(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int popcount(const T x) { return __builtin_popcountll(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x)   : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x)   : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clzll(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x)   : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x)   : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctzll(x) : suisen::bit_num<T>; }
template <typename T>
constexpr inline int floor_log2(const T x) { return suisen::bit_num<T> - 1 - count_lz(x); }
template <typename T>
constexpr inline int ceil_log2(const T x)  { return floor_log2(x) + ((x & -x) != x); }
template <typename T>
constexpr inline int kth_bit(const T x, const unsigned int k) { return (x >> k) & 1; }
template <typename T>
constexpr inline int parity(const T x) { return popcount(x) & 1; }

struct all_subset {
    struct all_subset_iter {
        const int s; int t;
        constexpr all_subset_iter(int s) : s(s), t(s + 1) {}
        constexpr auto operator*() const { return t; }
        constexpr auto operator++() {}
        constexpr auto operator!=(std::nullptr_t) { return t ? (--t &= s, true) : false; }
    };
    int s;
    constexpr all_subset(int s) : s(s) {}
    constexpr auto begin() { return all_subset_iter(s); }
    constexpr auto end()   { return nullptr; }
};

// ! container

template <typename T, typename Comparator, suisen::constraints_t<suisen::is_comparator<Comparator, T>> = nullptr>
auto priqueue_comp(const Comparator comparator) {
    return std::priority_queue<T, std::vector<T>, Comparator>(comparator);
}

template <typename Iterable>
auto isize(const Iterable &iterable) -> decltype(int(iterable.size())) {
    return iterable.size();
}

template <typename T, typename Gen, suisen::constraints_t<suisen::is_same_as_invoke_result<T, Gen, int>> = nullptr>
auto generate_vector(int n, Gen generator) {
    std::vector<T> v(n);
    for (int i = 0; i < n; ++i) v[i] = generator(i);
    return v;
}
template <typename T>
auto generate_range_vector(T l, T r) {
    return generate_vector(r - l, [l](int i) { return l + i; });
}
template <typename T>
auto generate_range_vector(T n) {
    return generate_range_vector(0, n);
}

template <typename T>
void sort_unique_erase(std::vector<T> &a) {
    std::sort(a.begin(), a.end());
    a.erase(std::unique(a.begin(), a.end()), a.end());
}

template <typename InputIterator, typename BiConsumer>
auto foreach_adjacent_values(InputIterator first, InputIterator last, BiConsumer f) -> decltype(f(*first++, *last), void()) {
    if (first != last) for (auto itr = first, itl = itr++; itr != last; itl = itr++) f(*itl, *itr);
}
template <typename Container, typename BiConsumer>
auto foreach_adjacent_values(Container c, BiConsumer f) -> decltype(c.begin(), c.end(), void()){
    foreach_adjacent_values(c.begin(), c.end(), f);
}

// ! other utilities

// x <- min(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmin(T &x, const T &y) {
    if (y >= x) return false;
    x = y;
    return true;
}
// x <- max(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmax(T &x, const T &y) {
    if (y <= x) return false;
    x = y;
    return true;
}

namespace suisen {}
using namespace suisen;
using namespace std;

struct io_setup {
    io_setup(int precision = 20) {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(precision);
    }
} io_setup_{};

// ! code from here

#include <utility>
#include <vector>

// l <= x < r
template <typename T>
constexpr inline bool in_range(const T &x, const T &l, const T &r) {
    return l <= x and x < r;
}
// 0 <= x < r
template <typename T>
constexpr inline bool in_range(const T &x, const T &r) {
    return (std::make_unsigned_t<T>) x < (std::make_unsigned_t<T>) r;
}
// not (l <= x < r)
template <typename T>
constexpr inline bool out_range(const T &x, const T &l, const T &r) {
    return x < l or r <= x;
}
// not (0 <= x < r)
template <typename T>
constexpr inline bool out_range(const T &x, const T &r) {
    return (std::make_unsigned_t<T>) x >= (std::make_unsigned_t<T>) r;
}

constexpr int dx4[4] = {1, 0, -1, 0};
constexpr int dy4[4] = {0, 1, 0, -1};
constexpr int dx8[8] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr int dy8[8] = {0, 1, 1, 1, 0, -1, -1, -1};

constexpr std::pair<int, int> dxy4[4] = {
    { dx4[0], dy4[0] }, { dx4[1], dy4[1] }, { dx4[2], dy4[2] }, { dx4[3], dy4[3] },
};
constexpr std::pair<int, int> dxy8[8] = {
    { dx8[0], dy8[0] }, { dx8[1], dy8[1] }, { dx8[2], dy8[2] }, { dx8[3], dy8[3] },
    { dx8[4], dy8[4] }, { dx8[5], dy8[5] }, { dx8[6], dy8[6] }, { dx8[7], dy8[7] },
};

template <int D, auto dx, auto dy>
struct AdjacentCells {
    struct Iterator {
        const int x, y;
        int d;
        bool operator!=(std::nullptr_t) { return d != D; }
        void operator++() { ++d; }
        std::pair<int, int> operator*() { return { x + dx[d], y + dy[d] }; }
    };
    const int x, y;
    AdjacentCells(int x, int y) : x(x), y(y) {}
    auto begin() { return Iterator { x, y, 0 }; }
    constexpr std::nullptr_t end() { return nullptr; }
    operator std::vector<std::pair<int, int>>() {
        std::vector<std::pair<int, int>> res;
        for (const auto &p : *this) res.push_back(p);
        return res;
    }
};

template <int D, auto dx, auto dy>
struct AdjacentCellsBounded {
    struct Iterator {
        const int x, y, xl, xr, yl, yr;
        int d;
        bool operator!=(std::nullptr_t) {
            for (; d != D; ++d) if (in_range(x + dx[d], xl, xr) and in_range(y + dy[d], yl, yr)) return true;
            return false;
        }
        void operator++() { ++d; }
        std::pair<int, int> operator*() { return { x + dx[d], y + dy[d] }; }
    };
    const int x, y, xl, xr, yl, yr;
    AdjacentCellsBounded(int x, int y, int xl, int xr, int yl, int yr) : x(x), y(y), xl(xl), xr(xr), yl(yl), yr(yr) {}
    AdjacentCellsBounded(int x, int y, int xr, int yr) : AdjacentCellsBounded(x, y, 0, xr, 0, yr) {}
    auto begin() { return Iterator { x, y, xl, xr, yl, yr, 0 }; }
    constexpr std::nullptr_t end() { return nullptr; }
    operator std::vector<std::pair<int, int>>() {
        std::vector<std::pair<int, int>> res;
        for (const auto &p : *this) res.push_back(p);
        return res;
    }
};

// [ {x+dx4[i], y+dy4[i]} for i in range(4) ]
using AdjacentFourCells = AdjacentCells<4, dx4, dy4>;
// [ {nx:=x+dx4[i], ny:=y+dy4[i]} for i in range(4) if xl<=nx<xr and yl<=ny<yr ]
using AdjacentFourCellsBounded = AdjacentCellsBounded<4, dx4, dy4>;

// [ {x+dx8[i], y+dy8[i]} for i in range(8) ]
using AdjacentEightCells = AdjacentCells<8, dx8, dy8>;
// [ {nx:=x+dx8[i], ny:=y+dy8[i]} for i in range(8) if xl<=nx<xr and yl<=ny<yr ]
using AdjacentEightCellsBounded = AdjacentCellsBounded<8, dx8, dy8>;

// [ {x+dx4[i], y+dy4[i]} for i in range(4) ]
auto adjacent_four_cells(int x, int y) { return AdjacentFourCells { x, y }; }
// [ {nx:=x+dx4[i], ny:=y+dy4[i]} for i in range(4) if xl<=nx<xr and yl<=ny<yr ]
auto adjacent_four_cells(int x, int y, int xl, int xr, int yl, int yr) { return AdjacentFourCellsBounded { x, y, xl, xr, yl, yr }; }
// [ {nx:=x+dx4[i], ny:=y+dy4[i]} for i in range(4) if 0 <=nx<xr and 0 <=ny<yr ]
auto adjacent_four_cells(int x, int y,         int xr,         int yr) { return AdjacentFourCellsBounded { x, y, 0 , xr, 0 , yr }; }

// [ {x+dx8[i], y+dy8[i]} for i in range(8) ]
auto adjacent_eight_cells(int x, int y) { return AdjacentEightCells { x, y }; }
// [ {nx:=x+dx8[i], ny:=y+dy8[i]} for i in range(8) if xl<=nx<xr and yl<=ny<yr ]
auto adjacent_eight_cells(int x, int y, int xl, int xr, int yl, int yr) { return AdjacentEightCellsBounded { x, y, xl, xr, yl, yr }; }
// [ {nx:=x+dx8[i], ny:=y+dy8[i]} for i in range(8) if 0 <=nx<xr and 0 <=ny<yr ]
auto adjacent_eight_cells(int x, int y,         int xr,         int yr) { return AdjacentEightCellsBounded { x, y, 0 , xr, 0 , yr }; }

long long solve(int h, int w) {
    if (h % 2 == 1 and w % 2 == 1) return 0;
    if (h > w) swap(h, w);

    if (min(h, w) == 1) return 1;

    const int m = h * w / 2;

    auto f = [](int x, int y) {
        return x >= 0 and y >= 0 and x != y;
    };

    set<vector<int>> st;

    auto normalize = [&](vector<vector<int>>& g) {
        rep(i, h - 1) rep(j, w - 1) {
            if (g[i][j] != g[i][j + 1] and g[i][j + 1] != g[i + 1][j + 1] and g[i + 1][j + 1] != g[i + 1][j] and g[i + 1][j] != g[i][j]) {
                return;
            }
        }

        vector<int> res;
        int id = 0;
        rep(i, h) rep(j, w - 1) {
            if (g[i][j] == g[i][j + 1]) res.push_back(id);
            ++id;
        }
        rep(i, h - 1) rep(j, w) {
            if (g[i][j] == g[i + 1][j]) res.push_back(id);
            ++id;
        }
        if (st.count(res)) return;
        st.insert(res);
    };

    auto dfs = [&](auto dfs, vector<vector<int>> g, int next_id) -> void {
        if (next_id == m) {
            normalize(g);
            return;
        }

        while (true) {
            int old_id = next_id;
            rep(i, h) rep(j, w - 1) {
                if (g[i][j] >= 0 or g[i][j + 1] >= 0) continue;
                if (i > 0 and f(g[i - 1][j], g[i - 1][j + 1])) {
                    g[i][j] = g[i][j + 1] = next_id++;
                } else if (i + 1 < h and f(g[i + 1][j], g[i + 1][j + 1])) {
                    g[i][j] = g[i][j + 1] = next_id++;
                }
            }
            rep(i, h - 1) rep(j, w) {
                if (g[i][j] >= 0 or g[i + 1][j] >= 0) continue;
                if (j > 0 and f(g[i][j - 1], g[i + 1][j - 1])) {
                    g[i][j] = g[i + 1][j] = next_id++;
                } else if (j + 1 < w and f(g[i][j + 1], g[i + 1][j + 1])) {
                    g[i][j] = g[i + 1][j] = next_id++;
                }
            }

            rep(i, h) rep(j, w) {
                if (g[i][j] >= 0) continue;

                int xi = -1, xj = -1;
                int adj_cnt = 0;
                for (auto [ni, nj] : adjacent_four_cells(i, j, h, w)) if (g[ni][nj] < 0) {
                    ++adj_cnt;
                    xi = ni, xj = nj;
                }
                if (adj_cnt != 1) continue;

                g[i][j] = g[xi][xj] = next_id++;
            }

            if (old_id == next_id) break;
        }

        if (next_id == m) {
            normalize(g);
            return;
        }

        rep(i, h) rep(j, w) {
            if (g[i][j] >= 0) continue;

            vector<pair<int, int>> ns;
            for (auto [ni, nj] : adjacent_four_cells(i, j, h, w)) if (g[ni][nj] < 0) {
                ns.emplace_back(ni, nj);
            }
            if (ns.size() != 2) continue;
            for (auto [ni, nj] : ns) {
                g[i][j] = g[ni][nj] = next_id;
                dfs(dfs, g, next_id + 1);
                g[i][j] = g[ni][nj] = -1;
            }
            return;
        }
    };

    rep(si, h - 1) rep(sj, w - 1) {
        vector<vector<int>> g(h, vector<int>(w, -1));
        g[si + 0][sj + 0] = g[si + 0][sj + 1] = 0;
        g[si + 1][sj + 0] = g[si + 1][sj + 1] = 1;
        dfs(dfs, g, 2);
    }

    rep(si, h - 1) rep(sj, w - 1) {
        vector<vector<int>> g(h, vector<int>(w, -1));
        g[si + 0][sj + 0] = g[si + 1][sj + 0] = 0;
        g[si + 0][sj + 1] = g[si + 1][sj + 1] = 1;
        dfs(dfs, g, 2);
    }

    return st.size();
}

int main() {
    while (true) {
        input(int, h, w);
        if (h == 0 and w == 0) return 0;
        print(solve(h, w));
    }
    return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 3240
final_rank: 8

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <cstdio>
#include <ctime>
#include <assert.h>
#include <chrono>
#include <random>
#include <numeric>
#include <set>
#include <deque>
#include <stack>
#include <sstream>
#include <utility>
#include <cstring>
#include <unordered_map>
#include <unordered_set>
#include <tuple>
#include <array>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int h,w;
    while(cin >> h >> w, h){
        int res = 0;
        vector<vector<int>> v(h,vector<int>(w));
        auto dfs=[&](auto dfs,int x,int y,int cur)->void{
            if(x == h){
                res++; return;
            }
            if(y == w){
                dfs(dfs,x+1,0,cur);
                return;
            }
            if(v[x][y]){
                dfs(dfs,x+(y==w),(y==w?0:y+1),cur);
                return;
            }
            if(x and y){
                if(v[x-1][y-1] != v[x-1][y] and v[x-1][y-1] != v[x][y-1] and v[x-1][y] != v[x][y-1])return;
            }
            if(y+1<w and !v[x][y+1]){
                v[x][y] = cur;
                v[x][y+1] = cur;
                dfs(dfs,x,y,cur+1);
                v[x][y] = 0;
                v[x][y+1] = 0;
            }
            if(x+1<h and !v[x+1][y]){
                v[x][y] = cur;
                v[x+1][y] = cur;
                dfs(dfs,x,y+1,cur+1);
                v[x][y] = 0;
                v[x+1][y] = 0;
            }
        };
        dfs(dfs,0,0,1);
        cout << res << "\n";
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3288
final_rank: 9

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
//const int mod = 1e9 + 7;
const int mod = 998244353;

int main(){
	while(1){
		int h,w; cin >> h >> w;
		if(!h) break;
		vvl v(h,vl(w,-1));
		ll ans = 0;
		int num = 0;
		auto dfs = [&](auto &&dfs, int y, int x) -> void {
			if(y == h){
				//rep(i,h) debug(v[i]);
				ans++; return;
			}
			int ny = y, nx = x+1;
			if(nx == w) ny = y+1, nx = 0;
			if(v[y][x] > -1){
				dfs(dfs,ny,nx);
				return;
			}
			bool f = false;
			if(y>0 && x>0){
				if(v[y][x] == v[y-1][x]) f = true;
				if(v[y][x] == v[y][x-1]) f = true;
				if(v[y-1][x-1] == v[y-1][x]) f = true;
				if(v[y-1][x-1] == v[y][x-1]) f = true;
			}else{
				f = true;
			}
			if(!f) return;
			v[y][x] = num;
			if(y < h-1 && v[y+1][x] == -1){
				v[y+1][x] = num;
				num++;
				dfs(dfs,ny,nx);
				num--;
				v[y+1][x] = -1;
			}
			if(x < w-1 && v[y][x+1] == -1){
				v[y][x+1] = num;
				num++;
				dfs(dfs,ny,nx);
				num--;
				v[y][x+1] = -1;
			}
			v[y][x] = -1;
		};
		dfs(dfs,0,0);
		cout << ans << "\n";
	}
}
accuracy: 1
time_ms: 70
memory_kb: 3208
final_rank: 7

code_snippet: #include<iostream>
using namespace std;
int H,W;
int ans;
void dfs(int x,int y,int a,int b)
{
	if(y==W)
	{
		dfs(x+1,0,a,b);
		return;
	}
	if(x==H)
	{
		if(a==0)ans++;
		return;
	}
	if(a>>y&1)
	{
		a^=1<<y;
		if(y>0)
		{
			b|=1<<y-1;
			if(a>>y-1&1)b^=1<<y-1;
		}
		dfs(x,y+1,a,b);
		return;
	}
	if(!(b>>y&1))
	{
		int na=a,nb=b;
		na|=1<<y;
		if(y>0&&a>>y-1&1)
		{
			nb|=1<<y-1;
		}
		dfs(x,y+1,na,nb);
	}
	if(y<W-1&&!(b>>y+1&1)&&!(a>>y+1&1))
	{
		int na=a,nb=b;
		nb|=1<<y;
		nb^=1<<y;
		if(y>0&&!(a>>y-1&1))
		{
			nb|=1<<y-1;
		}
		dfs(x,y+2,na,nb);
	}
}
main()
{
	while(cin>>H>>W,H)
	{
		ans=0;
		dfs(0,0,0,0);
		cout<<ans<<endl;
	}
}
accuracy: 1
time_ms: 40
memory_kb: 2992
final_rank: 1

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-12;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

int ans = 0;

void func(vector<vector<int>>&v, int y = 0, int x = 0, int cnt = 0) {
	if (cnt == H * W / 2) {
		ans++;
		return;
	}
	while (v[y][x] != -1) {
		x++;
		if (x == W) {
			x = 0;
			y++;
		}
	}
	if (x + 1 != W && v[y][x + 1] == -1) {
		v[y][x] = v[y][x + 1] = cnt;
		bool flag = true;
		if (y&&x) {
			int num = 0;
			if (v[y][x] != v[y][x - 1])num++;
			if (v[y][x] != v[y - 1][x])num++;
			if (v[y - 1][x - 1] != v[y][x - 1])num++;
			if (v[y - 1][x - 1] != v[y - 1][x])num++;
			if (num == 4)flag = false;
		}
		if (y&&x + 2 < W&&v[y][x + 2] != -1) {
			int num = 0;
			if (v[y][x + 1] != v[y][x + 2])num++;
			if (v[y][x + 1] != v[y - 1][x + 1])num++;
			if (v[y - 1][x + 2] != v[y][x + 2])num++;
			if (v[y - 1][x + 2] != v[y - 1][x + 1])num++;
			if (num == 4)flag = false;
		}
		if (flag) {
			func(v, y, x, cnt + 1);
		}
		v[y][x] = v[y][x + 1] = -1;
	}
	if (y + 1 != H && v[y + 1][x] == -1) {
		v[y][x] = v[y + 1][x] = cnt;
		bool flag = true;
		if (y&&x) {
			int num = 0;
			if (v[y][x] != v[y][x - 1])num++;
			if (v[y][x] != v[y - 1][x])num++;
			if (v[y - 1][x - 1] != v[y][x - 1])num++;
			if (v[y - 1][x - 1] != v[y - 1][x])num++;
			if (num == 4)flag = false;
		}
		if (y&&x + 1 < W&&v[y][x + 1] != -1) {
			int num = 0;
			if (v[y][x] != v[y][x + 1])num++;
			if (v[y][x] != v[y - 1][x])num++;
			if (v[y - 1][x + 1] != v[y][x + 1])num++;
			if (v[y - 1][x + 1] != v[y - 1][x])num++;
			if (num == 4)flag = false;
		}
		if (flag) {
			func(v, y, x, cnt + 1);
		}
		v[y][x] = v[y + 1][x] = -1;
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	while (cin >> H >> W, H) {
		ans = 0;
		if (H*W % 2 == 1) {
			cout << 0 << endl;
			continue;
		}
		vector<vector<int>>v(H, vector<int>(W, -1));
		func(v);
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 110
memory_kb: 3140
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=55,INF=1<<30;
int H,W;
vector<vector<int>> S;
int now;

bool check(){
    int cnt=0;
    for(int i=0;i<H;i++){
        for(int j=0;j<W;j++){
            if(cnt==(now-1)*2) return true;
            if(S[i][j]) cnt++;
            if(i==H-1||j==W-1) break;
            if(S[i][j]==0||S[i+1][j]==0||S[i][j+1]==0||S[i+1][j+1]==0) continue;
            if(S[i][j]!=S[i][j+1]&&S[i][j]!=S[i+1][j]&&S[i+1][j]!=S[i+1][j+1]&&S[i][j+1]!=S[i+1][j+1]) return false;
        }
    }
    return true;
}

int DFS(){
    if(!check()) return 0;
    
    if(now==H*W/2+1) return 1;
    
    int res=0;
    
    for(int i=0;i<H;i++){
        for(int j=0;j<W;j++){
            if(S[i][j]) continue;
            
            if(i+1<H&&S[i+1][j]==0){
                S[i][j]=now;
                S[i+1][j]=now;
                now++;
                res+=DFS();
                now--;
                S[i][j]=0;
                S[i+1][j]=0;
            }
            
            if(j+1<W&&S[i][j+1]==0){
                S[i][j]=now;
                S[i][j+1]=now;
                now++;
                res+=DFS();
                now--;
                S[i][j]=0;
                S[i][j+1]=0;
            }
            
            return res;
        }
    }
    
    return res;
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        cin>>H>>W;
        if(H==0) break;
        if((H*W)&1){
            cout<<0<<endl;
            continue;
        }
        S.resize(H);
        for(int i=0;i<H;i++) S[i].assign(W,0);
        now=1;
        cout<<DFS()<<endl;
    }
}
accuracy: 1
time_ms: 1770
memory_kb: 3128
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=55,INF=1<<30;
int H,W;
vector<vector<int>> S;
int now;

bool check(){
    for(int i=0;i+1<H;i++){
        for(int j=0;j+1<W;j++){
            if(S[i][j]==0||S[i+1][j]==0||S[i][j+1]==0||S[i+1][j+1]==0) continue;
            if(S[i][j]!=S[i][j+1]&&S[i][j]!=S[i+1][j]&&S[i+1][j]!=S[i+1][j+1]&&S[i][j+1]!=S[i+1][j+1]) return false;
        }
    }
    return true;
}

int DFS(){
    if(!check()) return 0;
    
    if(now==H*W/2+1) return 1;
    
    int res=0;
    
    for(int i=0;i<H;i++){
        for(int j=0;j<W;j++){
            if(S[i][j]) continue;
            
            if(i+1<H&&S[i+1][j]==0){
                S[i][j]=now;
                S[i+1][j]=now;
                now++;
                res+=DFS();
                now--;
                S[i][j]=0;
                S[i+1][j]=0;
            }
            
            if(j+1<W&&S[i][j+1]==0){
                S[i][j]=now;
                S[i][j+1]=now;
                now++;
                res+=DFS();
                now--;
                S[i][j]=0;
                S[i][j+1]=0;
            }
            
            return res;
        }
    }
    
    return res;
}

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        cin>>H>>W;
        if(H==0) break;
        if((H*W)&1){
            cout<<0<<endl;
            continue;
        }
        S.resize(H);
        for(int i=0;i<H;i++) S[i].assign(W,0);
        now=1;
        cout<<DFS()<<endl;
    }
}
accuracy: 1
time_ms: 2940
memory_kb: 3204
final_rank: 15

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<utility>
#include<map>
#include<complex>
#include<stack>
using namespace std;
typedef long long ll;
const ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int> P;
typedef pair<ll, ll> LP;
typedef vector<int> vec;
#define rep(i,n) for(int i=0;i<n;i++)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define stop char nyaa;cin>>nyaa;
#define per(i,n) for(int i=n-1;i>=0;i--)
typedef long double ld;

int h, w;
int a[20][20];
int ans;
void dfs(int i, int j,int cur) {
	if (i == h) {
		/*cout << endl;
		rep(i, h) {
			rep(j, w) {
				cout << a[i][j];
			}
			cout << endl;
		}*/
		ans++; return;
	}
	int ni = i, nj = j + 1; if (nj == w)ni = ni + 1, nj = 0;
	if (a[i][j]) {
		dfs(ni, nj, cur); return;
	}
	//oo
	if (j < w - 1&&!a[i][j+1]) {
		a[i][j] = a[i][j + 1] = cur;
		bool f = true;
		if (j < w - 2&&i>0) {
			vector<int> v = { a[i - 1][j + 1],a[i][j + 1],a[i - 1][j + 2],a[i][j + 2] };
			sort(v.begin(), v.end());
			int len = unique(v.begin(), v.end()) - v.begin();
			if (len == 4)f = false;
		}
		if (f) {
			dfs(ni, nj, cur + 1);
		}
		a[i][j] = a[i][j + 1] = 0;
	}
	//else
	if (i < h - 1 && !a[i + 1][j]) {
		a[i][j] = a[i + 1][j] = cur;
		bool f = true;
		if (j < w - 1 && i>0) {
			vector<int> v = { a[i][j],a[i - 1][j],a[i][j + 1],a[i - 1][j + 1] };
			sort(v.begin(), v.end());
			int len = unique(v.begin(), v.end()) - v.begin();
			if (len == 4)f = false;
		}
		if (f) {
			dfs(ni, nj, cur + 1);
		}
		a[i][j] = a[i + 1][j] = 0;
	}
}
void solve() {
	ans = 0;
	dfs(0, 0, 1);
	cout << ans << endl;
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	while (cin >> h >> w, h) {
		solve();
	}
	//stop
		return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 3044
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;

using vi=vector<int>;
using vvi=vector<vi>;
int h,w;
int dfs(vvi &f,int x,int i);
vi flags;
bool check(const vvi &f,int k,int l){
    for(int i=max(k-1,0);i+1<h && i<=k+1;i++){
        for(int j=max(l-1,0);j+1<w && j<=l+1;j++){
            int zcnt=0;
            set<int> s;
            for(int di=0;di<2;di++){
                for(int dj=0;dj<2;dj++){
                    if(f[i+di][j+dj]!=0) s.insert(f[i+di][j+dj]);                      
                }
            }
            if(zcnt+s.size()==4) return false;
        }
    }
    return true;
}
int impl(vvi &f,int i,int j,int x){
    int res=0;
    int k=1;
    if(0<=i+k-1 && i+k<h && f[i+k-1][j]==f[i+k][j]){
        f[i+k-1][j]=f[i+k][j]=x;
        if(check(f,i,j)) res+=dfs(f,x+1,i);
        f[i+k-1][j]=f[i+k][j]=0;
    }
    if(0<=j+k-1 && j+k<w && f[i][j+k-1]==f[i][j+k]){
        f[i][j+k-1]=f[i][j+k]=x;
        if(check(f,i,j)) res+=dfs(f,x+1,i);
        f[i][j+k-1]=f[i][j+k]=0;
    }
    return res;
}
int dfs(vvi &f,int x,int i){
    if(i==h) return 1;
    for(int j=0;j<w;j++){
        if(!f[i][j]){
            return impl(f,i,j,x);
        }
    }
    return dfs(f,x,i+1);
}
int solve(){
    flags.assign(h*w,0);
    vvi tmpf(h,vi(w,0));
    return dfs(tmpf,1,0);
}

int main(){
    while(cin>>h>>w,h){
        cout<<solve()<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 3420
memory_kb: 3108
final_rank: 16

code_snippet: #include <bits/stdc++.h>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<int,int> P;

struct data{
	int fie[23][23];
	bool dir[23][23][4];
	int cnt[23][23];
};

int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int h,w;
int fie[23][23];
bool dir[23][23][4];
int cnt[23][23];
int ans=0;

stack<data> sta;

void push(){
	data dat;
	for(int i=0;i<h;i++){
		for(int j=0;j<w;j++){
			dat.fie[i][j]=fie[i][j];
			dat.cnt[i][j]=cnt[i][j];
			for(int k=0;k<4;k++){
				dat.dir[i][j][k]=dir[i][j][k];
			}
		}
	}
	sta.push(dat);
}

void pop(){
	data dat=sta.top();
	sta.pop();
	for(int i=0;i<h;i++){
		for(int j=0;j<w;j++){
			fie[i][j]=dat.fie[i][j];
			cnt[i][j]=dat.cnt[i][j];
			for(int k=0;k<4;k++){
				dir[i][j][k]=dat.dir[i][j][k];
			}
		}
	}
}

void check(int y,int x){
	if(y<0 || y>=h || x<0 || x>=w)return;
	for(int i=0;i<4;i++){
		if(dir[y][x][i])continue;
		if(fie[y][x] || fie[y+dy[i]][x+dx[i]]){
			dir[y][x][i]=true;
			cnt[y][x]++;
		}
	}
}

void dfs(int c){
	if(c*2==h*w){
		ans++;
		return;
	}
	int nx=0,ny=0;
	for(int i=0;i<h;i++){
		for(int j=0;j<w;j++){
			if(fie[i][j])continue;
			if(cnt[i][j]==4 && !fie[i][j])return;
			if(fie[ny][nx] || cnt[ny][nx]<cnt[i][j]){
				ny=i;
				nx=j;
			}
		}
	}
	if(fie[ny][nx] || cnt[ny][nx]==4)return;
	for(int i=0;i<4;i++){
		if(dir[ny][nx][i])continue;
		push();
		fie[ny][nx]=c+1;
		fie[ny+dy[i]][nx+dx[i]]=c+1;
		for(int j=ny-2;j<=ny+2;j++){
			for(int k=nx-2;k<=nx+2;k++){
				check(j,k);
			}
		}
		if(i%2==1){
			if(i>=2)nx--;
			if(ny-1>=0 && nx-1>=0){
				if(!dir[ny-1][nx-1][2]){
					cnt[ny-1][nx-1]++;
				}
				dir[ny-1][nx-1][2]=true;
				if(ny-2>=0){
					if(!dir[ny-2][nx-1][0]){
						cnt[ny-2][nx-1]++;
					}
					dir[ny-2][nx-1][0]=true;
				}
				if(!dir[ny-1][nx-1][3]){
					cnt[ny-1][nx-1]++;
				}
				dir[ny-1][nx-1][3]=true;
				if(nx-2>=0){
					if(!dir[ny-1][nx-2][1]){
						cnt[ny-1][nx-2]++;
					}
					dir[ny-1][nx-2][1]=true;
				}
			}
			if(ny-1>=0){
				if(!dir[ny-1][nx+2][2]){
					cnt[ny-1][nx+2]++;
				}
				dir[ny-1][nx+2][2]=true;
				if(ny-2>=0){
					if(!dir[ny-2][nx+2][0]){
						cnt[ny-2][nx+2]++;
					}
					dir[ny-2][nx+2][0]=true;
				}
				if(!dir[ny-1][nx+2][1]){
					cnt[ny-1][nx+2]++;
				}
				dir[ny-1][nx+2][1]=true;

				if(!dir[ny-1][nx+3][3]){
					cnt[ny-1][nx+3]++;
				}
				dir[ny-1][nx+3][3]=true;
			}
			if(nx-1>=0){
				if(!dir[ny+1][nx-1][0]){
					cnt[ny+1][nx-1]++;
				}
				dir[ny+1][nx-1][0]=true;
				if(!dir[ny+2][nx-1][2]){
					cnt[ny+2][nx-1]++;
				}
				dir[ny+2][nx-1][2]=true;

				if(!dir[ny+1][nx-1][3]){
					cnt[ny+1][nx-1]++;
				}
				dir[ny+1][nx-1][3]=true;
				if(nx-2>=0){
					if(!dir[ny+1][nx-2][1]){
						cnt[ny+1][nx-2]++;
					}
					dir[ny+1][nx-2][1]=true;
				}
			}
			if(!dir[ny+1][nx+2][0]){
				cnt[ny+1][nx+2]++;
			}
			dir[ny+1][nx+2][0]=true;
			if(!dir[ny+2][nx+2][2]){
				cnt[ny+2][nx+2]++;
			}
			dir[ny+2][nx+2][2]=true;
			if(!dir[ny+1][nx+2][1]){
				cnt[ny+1][nx+2]++;
			}
			dir[ny+1][nx+2][1]=true;
			if(!dir[ny+1][nx+3][3]){
				cnt[ny+1][nx+3]++;
			}
			dir[ny+1][nx+3][3]=true;
		}else{
			if(i>=2)ny--;
			if(ny-1>=0 && nx-1>=0){
				if(!dir[ny-1][nx-1][2]){
					cnt[ny-1][nx-1]++;
				}
				dir[ny-1][nx-1][2]=true;
				if(ny-2>=0){
					if(!dir[ny-2][nx-1][0]){
						cnt[ny-2][nx-1]++;
					}
					dir[ny-2][nx-1][0]=true;
				}
				if(!dir[ny-1][nx-1][3]){
					cnt[ny-1][nx-1]++;
				}
				dir[ny-1][nx-1][3]=true;
				if(nx-2>=0){
					if(!dir[ny-1][nx-2][1]){
						cnt[ny-1][nx-2]++;
					}
					dir[ny-1][nx-2][1]=true;
				}
			}
			if(ny-1>=0){
				if(!dir[ny-1][nx+1][2]){
					cnt[ny-1][nx+1]++;
				}
				dir[ny-1][nx+1][2]=true;
				if(ny-2>=0){
					if(!dir[ny-2][nx+1][0]){
						cnt[ny-2][nx+1]++;
					}
					dir[ny-2][nx+1][0]=true;
				}
				if(!dir[ny-1][nx+1][1]){
					cnt[ny-1][nx+1]++;
				}
				dir[ny-1][nx+1][1]=true;

				if(!dir[ny-1][nx+2][3]){
					cnt[ny-1][nx+2]++;
				}
				dir[ny-1][nx+2][3]=true;
			}
			if(nx-1>=0){
				if(!dir[ny+2][nx-1][0]){
					cnt[ny+2][nx-1]++;
				}
				dir[ny+2][nx-1][0]=true;
				if(!dir[ny+3][nx-1][2]){
					cnt[ny+3][nx-1]++;
				}
				dir[ny+3][nx-1][2]=true;

				if(!dir[ny+2][nx-1][3]){
					cnt[ny+2][nx-1]++;
				}
				dir[ny+2][nx-1][3]=true;
				if(nx-2>=0){
					if(!dir[ny+2][nx-2][1]){
						cnt[ny+2][nx-2]++;
					}
					dir[ny+2][nx-2][1]=true;
				}
			}
			if(!dir[ny+2][nx+1][0]){
				cnt[ny+2][nx+1]++;
			}
			dir[ny+2][nx+1][0]=true;
			if(!dir[ny+3][nx+1][2]){
				cnt[ny+3][nx+1]++;
			}
			dir[ny+3][nx+1][2]=true;
			if(!dir[ny+2][nx+1][1]){
				cnt[ny+2][nx+1]++;
			}
			dir[ny+2][nx+1][1]=true;
			if(!dir[ny+2][nx+2][3]){
				cnt[ny+2][nx+2]++;
			}
			dir[ny+2][nx+2][3]=true;
		}
		dfs(c+1);
		pop();
	}
}


void solve(){
	if(h*w%2==1){
		printf("0\n");
		return;
	}
	ans=0;
	memset(fie,false,sizeof(fie));
	memset(dir,false,sizeof(dir));
	memset(cnt,0,sizeof(cnt));
	for(int i=0;i<h;i++){
		cnt[i][0]++;
		dir[i][0][3]=true;
		cnt[i][w-1]++;
		dir[i][w-1][1]=true;
	}
	for(int i=0;i<w;i++){
		cnt[0][i]++;
		dir[0][i][2]=true;
		cnt[h-1][i]++;
		dir[h-1][i][0]=true;
	}
	dfs(0);
	printf("%d\n",ans);
}

int main(void){
	while(1){
		scanf("%d%d",&h,&w);
		if(h==0 && w==0)return 0;
		solve();
	}
	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 4292
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;

#define fi first
#define se second
#define repl(i,a,b) for(ll i=(ll)(a);i<(ll)(b);i++)
#define rep(i,n) repl(i,0,n)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<x<<endl
#define mmax(x,y) (x>y?x:y)
#define mmin(x,y) (x<y?x:y)
#define maxch(x,y) x=mmax(x,y)
#define minch(x,y) x=mmin(x,y)
#define uni(x) x.erase(unique(all(x)),x.end())
#define exist(x,y) (find(all(x),y)!=x.end())
#define bcnt __builtin_popcount

#define INF 1e16
#define mod 1000000007

int h,w;
int res;
int crtnum;
int num[22][22];

void dfs(int i,int j){
  if(i==h){
    bool ok=true;
    rep(a,h-1){
      rep(b,w-1){
        vector<int> tmp;
        tmp.push_back(num[a][b]); tmp.push_back(num[a][b+1]); tmp.push_back(num[a+1][b]); tmp.push_back(num[a+1][b+1]);
        sort(all(tmp)); uni(tmp);
        if(tmp.size()==4){
          ok=false;
          break;
        }
      }
      if(!ok)break;
    }
    if(ok)res++;
    return ;
  }
  int ni,nj;
  if(j==w-1){
    ni=i+1; nj=0;
  }else{
    ni=i; nj=j+1;
  }

  if(j+1<w&&num[i][j]==-1&&num[i][j+1]==-1){
    num[i][j]=num[i][j+1]=crtnum++;

    bool ok=true;
    for(int ci=max(0,i-1);ci<=min(h-1,i);ci++){
      for(int cj=max(0,j-1);cj<=min(w-1,j+1);cj++){
        vector<int> tmp;
        tmp.push_back(num[ci][cj]); tmp.push_back(num[ci][cj+1]); tmp.push_back(num[ci+1][cj]); tmp.push_back(num[ci+1][cj+1]);
        sort(all(tmp)); uni(tmp);
        if(tmp[0]!=-1&&tmp.size()==4){
          ok=false;
          break;
        }
      }
      if(!ok)break;
    }

    if(ok)dfs(ni,nj);
    num[i][j]=num[i][j+1]=-1;
    crtnum--;
  }
  if(i+1<h&&num[i][j]==-1&&num[i+1][j]==-1){
    num[i][j]=num[i+1][j]=crtnum++;
    
    bool ok=true;
    for(int ci=max(0,i-1);ci<=min(h-1,i+1);ci++){
      for(int cj=max(0,j-1);cj<=min(w-1,j);cj++){
        vector<int> tmp;
        tmp.push_back(num[ci][cj]); tmp.push_back(num[ci][cj+1]); tmp.push_back(num[ci+1][cj]); tmp.push_back(num[ci+1][cj+1]);
        sort(all(tmp)); uni(tmp);
        if(tmp[0]!=-1&&tmp.size()==4){
          ok=false;
          break;
        }
      }
      if(!ok)break;
    }

    if(ok)dfs(ni,nj);

    num[i][j]=num[i+1][j]=-1;
    crtnum--;
  }
  if(num[i][j]!=-1){
    dfs(ni,nj);
  }
}

int main(){
  while(1){
    cin>>h>>w;
    if(h==0)break;
    crtnum=0; res=0;
    memset(num,-1,sizeof(num));
    dfs(0,0);
    cout<<res<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 4820
memory_kb: 3068
final_rank: 18

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


enum Type{
	YOKO,
	TATE,
};


int H,W;
int ans,limit;

bool check(Type type,int row,int col,int table[20][20]){ //新しく角が寄った点だけ調べる

	int start_row,end_row,start_col,end_col;
	if(type == YOKO){
		start_col = max(1,col);
		end_col = min(W-1,col+2);
		start_row = max(1,row);
		end_row = min(H-1,row+1);

	}else{ //type == TATE

		start_col = max(1,col);
		end_col = min(W-1,col+1);
		start_row = max(1,row);
		end_row = min(H-1,row+2);
	}

	for(int row = start_row; row <= end_row; row++){
		for(int col = start_col; col <= end_col; col++){
			if(table[row-1][col-1] == 0 || table[row-1][col] == 0 || table[row][col-1] == 0 || table[row][col] == 0)continue;

			if(table[row-1][col-1] != table[row-1][col] && table[row-1][col-1] != table[row][col-1] && table[row-1][col-1] != table[row][col] &&
				table[row-1][col] != table[row][col-1] && table[row-1][col] != table[row][col] && table[row][col-1] != table[row][col])return false;

		}
	}
	return true;
}

void recursive(int count,int row,int col,int table[20][20]){ //重複計上を防ぐため、行ごとに畳を並べる
	if(row == H){
		if(count == limit+1)ans++;
		return;
	}
	if(col == W){ //次の行へ
		recursive(count,row+1,0,table);
		return;
	}

	if(table[row][col] != 0){ //既に畳が敷いてある(縦)
		if(col <= W-2){
			recursive(count,row,col+1,table);
		}else{ //col == W-1
			recursive(count,row+1,0,table); //次の行へ
		}
		return;
	}

	if(col <= W-2 && table[row][col+1] == 0){ //右に敷ける場合
		int next_table[20][20];
		for(int a = 0; a < H; a++){
			for(int b = 0; b < W; b++)next_table[a][b] = table[a][b];
		}
		next_table[row][col] = count;
		next_table[row][col+1] = count;

		if(check(YOKO,row,col,next_table)){
			recursive(count+1,row,col+2,next_table);
		}
	}
	if(row <= H-2 && table[row+1][col] == 0){ //縦に敷ける場合
		int next_table[20][20];
		for(int a = 0; a < H; a++){
			for(int b = 0; b < W; b++)next_table[a][b] = table[a][b];
		}
		next_table[row][col] = count;
		next_table[row+1][col] = count;

		if(check(TATE,row,col,next_table)){
			recursive(count+1,row,col+1,next_table);
		}

	}

}


int main(){

	int first_table[20][20];

	while(true){
		scanf("%d %d",&H,&W);
		if(H == 0 && W == 0)break;

		if((H*W)%2 == 1){
			printf("0\n");
			continue;
		}

		ans = 0;
		limit = (H*W)/2; //limit枚の畳が敷けるはず

		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++){
				first_table[row][col] = 0;
			}
		}
		recursive(1,0,0,first_table);

		printf("%d\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 1120
memory_kb: 3632
final_rank: 14

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


int H,W;
int ans,limit;

bool check(int table[20][20]){

	for(int row = 1; row <= H-1; row++){
		for(int col = 1; col <= W-1; col++){
			if(table[row-1][col-1] == 0 || table[row-1][col] == 0 || table[row][col-1] == 0 || table[row][col] == 0)continue;

			if(table[row-1][col-1] != table[row-1][col] && table[row-1][col-1] != table[row][col-1] && table[row-1][col-1] != table[row][col] &&
				table[row-1][col] != table[row][col-1] && table[row-1][col] != table[row][col] && table[row][col-1] != table[row][col])return false;

		}
	}
	return true;
}

void recursive(int count,int row,int col,int table[20][20]){ //重複計上を防ぐため、行ごとに畳を並べる
	if(row == H){
		if(count == limit+1)ans++;
		return;
	}
	if(col == W){ //次の行へ
		recursive(count,row+1,0,table);
		return;
	}

	if(table[row][col] != 0){ //既に畳が敷いてある(縦)
		if(col <= W-2){
			recursive(count,row,col+1,table);
		}else{ //col == W-1
			recursive(count,row+1,0,table); //次の行へ
		}
		return;
	}

	if(col <= W-2 && table[row][col+1] == 0){ //右に敷ける場合
		int next_table[20][20];
		for(int a = 0; a < H; a++){
			for(int b = 0; b < W; b++)next_table[a][b] = table[a][b];
		}
		next_table[row][col] = count;
		next_table[row][col+1] = count;

		if(check(next_table)){
			recursive(count+1,row,col+2,next_table);
		}
	}
	if(row <= H-2 && table[row+1][col] == 0){ //縦に敷ける場合
		int next_table[20][20];
		for(int a = 0; a < H; a++){
			for(int b = 0; b < W; b++)next_table[a][b] = table[a][b];
		}
		next_table[row][col] = count;
		next_table[row+1][col] = count;

		if(check(next_table)){
			recursive(count+1,row,col+1,next_table);
		}

	}

}


int main(){

	int first_table[20][20];

	while(true){
		scanf("%d %d",&H,&W);
		if(H == 0 && W == 0)break;

		if((H*W)%2 == 1){
			printf("0\n");
			continue;
		}

		ans = 0;
		limit = (H*W)/2; //limit枚の畳が敷けるはず

		for(int row = 0; row < H; row++){
			for(int col = 0; col < W; col++){
				first_table[row][col] = 0;
			}
		}
		recursive(1,0,0,first_table);

		printf("%d\n",ans);
	}

	return 0;
}
accuracy: 1
time_ms: 3620
memory_kb: 3700
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
    int H, W;
    while(cin >> H >> W, H) {
        vector<vector<int>> tatami(H, vector<int>(W, -1));

        auto cond_check = [&](int y, int x) {
            return y == 0 || x == 0
            || tatami[y - 1][x - 1] == tatami[y - 1][x] || tatami[y][x - 1] == tatami[y][x]
            || tatami[y - 1][x - 1] == tatami[y][x - 1] || tatami[y - 1][x] == tatami[y][x];
        };

        long long id = 0;
        function<int(int, int)> solve = [&](int y, int x) {
            if(y == H - 1 && x == W - 1 && tatami[y][x] != -1) return 1;
            if(x >= W) return solve(y + 1, 0);
            if(tatami[y][x] != -1) return solve(y, x + 1);
            if(!cond_check(y, x)) return 0;

            int res = 0;
            if(y + 1 < H) { // put vert
                tatami[y][x] = tatami[y + 1][x] = id++;
                res += solve(y, x + 1);
                tatami[y][x] = tatami[y + 1][x] = -1;
            }
            if(x + 1 < W && tatami[y][x + 1] == -1) { // put hori
                tatami[y][x] = tatami[y][x + 1] = id++;
                res += solve(y, x + 1);
                tatami[y][x] = tatami[y][x + 1] = -1;
            }

            return res;
        };

        cout << solve(0, 0) << endl;
    }
}
accuracy: 1
time_ms: 120
memory_kb: 3136
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using LL = long long;
using VL = vector<LL>;
using VVL = vector<VL>;
using PLL = pair<LL, LL>;
using VS = vector<string>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

#define FF first
#define SS second
template<class S, class T>
istream& operator>>(istream& is, pair<S,T>& p){
  return is >> p.FF >> p.SS;
}
template<class S, class T>
ostream& operator<<(ostream& os, const pair<S,T>& p){
  return os << p.FF << " " << p.SS;
}
template<class T>
void maxi(T& x, T y){
  if(x < y) x = y;
}
template<class T>
void mini(T& x, T y){
  if(x > y) x = y;
}


const double EPS = 1e-10;
const double PI  = acos(-1.0);
const LL MOD = 1e9+7;

int W, H;
int memo[21][21];
int dfs(int x, int y, int i){
  if(y == H)
	return 1;
  if(x == W)
	return dfs(0, y+1, i);

  if(memo[y][x])
	return dfs(x+1, y, i);

  int res = 0;
  if(x+1 < W && !memo[y][x+1]){
	if(!(y > 0 && x > 0 && memo[y-1][x-1] != memo[y-1][x] && memo[y-1][x-1] != memo[y][x-1])){
	  memo[y][x] = memo[y][x+1] = i;
	  res += dfs(x+1, y, i+1);
	  memo[y][x] = memo[y][x+1] = 0;
	}
  }
  if(y+1 < H && !memo[y+1][x]){
	if(!(y > 0 && x > 0 && memo[y-1][x-1] != memo[y-1][x] && memo[y-1][x-1] != memo[y][x-1])){
	  memo[y][x] = memo[y+1][x] = i;
	  res += dfs(x+1, y, i+1);
	  memo[y][x] = memo[y+1][x] = 0;
	}
  }
  return res;
}

int main(){
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  while(cin>>W>>H,W){
	cout << dfs(0,0,1) << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3140
final_rank: 4

code_snippet: #include <bits/stdc++.h>
#define r(i,n) for(int i=0;i<n;i++)
using namespace std;
int a[21][21],ans,c,h,w;
void dfs(int x,int y);
bool ch(int x,int y){
  return !(a[y][x-1]!=a[y-1][x-1]&&a[y-1][x]!=a[y-1][x-1]&&a[y][x-1]!=a[y-1][x]);
}
void in(int x,int y){
  if(x==w-1)dfs(0,y+1);
  else dfs(x+1,y);
}
void dfs(int x,int y){
  if(x==w-1&&y==h-1)ans++;
  else{
    if(a[y][x])in(x,y);
    else if(!x||!y||(ch(x,y))){
      int col=++c;
      a[y][x]=col;
      if(y!=h-1&&!a[y+1][x]){
        a[y+1][x]=col;
        in(x,y);
        a[y+1][x]=0;
      }
      if(x!=w-1&&!a[y][x+1]){
        a[y][x+1]=col;
        in(x,y);
        a[y][x+1]=0;
      }
      a[y][x]=0;
    }
  }
}
int main(){
  while(cin>>h>>w,h){
    memset(a,0,sizeof(a));
    ans=c=0;
    if(h%2==0||w%2==0)dfs(0,0);
    cout<<ans<<endl;
  }
}
accuracy: 1
time_ms: 70
memory_kb: 3064
final_rank: 2