#include namespace { #pragma GCC diagnostic ignored "-Wunused-function" #include #pragma GCC diagnostic warning "-Wunused-function" using namespace std; using namespace atcoder; #define rep(i,n) for(int i = 0; i < (int)(n); i++) #define rrep(i,n) for(int i = (int)(n) - 1; i >= 0; i--) #define all(x) begin(x), end(x) #define rall(x) rbegin(x), rend(x) template bool chmax(T& a, const T& b) { if (a < b) { a = b; return true; } else return false; } template bool chmin(T& a, const T& b) { if (b < a) { a = b; return true; } else return false; } using ll = unsigned long long; using P = pair; using VI = vector; using VVI = vector; using VL = vector; using VVL = vector; } int main() { ios::sync_with_stdio(false); cin.tie(0); constexpr int M = 8; VL cs[M][M], ts[M][M]; rep(si, M) rep(sj, M) { int d[M][M]{}; auto f = [&](auto&& reg) { rep(_, 4) { [&]() { ll bit = 0; int bi = -1, bj = -1; rrep(i, M) rrep(j, M) { if (d[i][j]) bit |= 1ULL << (i * M + j), bi = i, bj = j; } assert(bi != -1); reg[bi][bj].emplace_back(bit); }(); int nd[M][M]{}; rep(i, M) rep(j, M) nd[i][j] = d[M-1-j][i]; memcpy(d, nd, sizeof(d)); } }; // c for (int l1 = 2; sj + l1 <= M; l1++) { for (int l2 = 3; si + l2 <= M; l2++) { for (int l3 = 2; sj + l3 <= M; l3++) { memset(d, 0, sizeof(d)); rep(k, l1) d[si][sj+k] = 1; rep(k, l2) d[si+k][sj] = 1; rep(k, l3) d[si+l2-1][sj+k] = 1; f(cs); } } } // t for (int l1 = 2; l1 <= sj; l1++) { for (int l2 = 2; sj + l2 <= M; l2++) { for (int l3 = 2; si + l3 <= M; l3++) { memset(d, 0, sizeof(d)); rep(k, l1) d[si][sj-k] = 1; rep(k, l2) d[si][sj+k] = 1; rep(k, l3) d[si+k][sj] = 1; f(ts); } } } } auto find_sol = [&](int h, int w, int mode) -> VL& { static VL memo[M+1][M+1][4]; static bool valid[M+1][M+1][4]; if (valid[h][w][mode]) return memo[h][w][mode]; VL trans[M][M]; auto add = [&](auto&& src, auto&& dest) { rep(i, h) rep(j, w) { for (ll b : src[i][j]) { bool ok = true; rep(i, M) rep(j, M) ok &= (i < h && j < w) || (~b >> (i * M + j) & 1); if (ok) dest[i][j].emplace_back(b); } } }; if (mode & 1) add(cs, trans); if (mode & 2) add(ts, trans); VL sol; auto dfs = [&](auto&& self, int i, int j, ll used) -> bool { if (j == w) i++, j = 0; if (i == h) return true; if (used >> (i * M + j) & 1) { return self(self, i, j + 1, used); } else { for (ll b : trans[i][j]) if (!(b & used)) { sol.emplace_back(b); bool res = self(self, i, j + 1, used | b); if (res) return true; sol.pop_back(); } return false; } }; ll used = ~0ULL; rep(i, h) rep(j, w) used ^= 1ULL << (i * M + j); dfs(dfs, 0, 0, used); valid[h][w][mode] = true; return memo[h][w][mode] = move(sol); }; // int mode; // cin >> mode; // for (int h = 1; h <= M; h++) { // for (int w = 1; w <= M; w++) { // auto sol = find_sol(h, w, mode); // bool res = !sol.empty(); // if (w == 1) cout << h << ": "; // cout << res; // if (w == M) cout << '\n'; // } // } int h, w; cin >> h >> w; VVI a(h, VI(w)); for (int mode = 1; mode <= 3; mode++) { bool ok = mode == 1 ? min(h, w) >= 4 || (min(h, w) == 3 && max(h, w) % 2 == 0) : mode == 2 ? min(h, w) >= 4 : min(h, w) >= 3; if (!ok) { cout << -1 << '\n'; continue; } int id = 0; for (int i = h; i;) { int hh = i >= 8 ? 4 : i; i -= hh; for (int j = w; j;) { int ww = j >= 8 ? 4 : j; j -= ww; VL& sol = find_sol(hh, ww, mode); assert(!sol.empty()); for (ll b : sol) { id++; rep(ii, hh) rep(jj, ww) if (b >> (ii * M + jj) & 1) a[i+ii][j+jj] = id; } } } cout << id << '\n'; rep(i, h) rep(j, w) cout << a[i][j] << " \n"[j + 1 == w]; } }