#yukicoder2958 Placing Many L-s #実験コードを書く def brute(H, W): def make_valid(): block = [] for G in ([[1, 1, 1], [x, 0, x ^ 1], [0, 0, 0]] for x in range(2)): for _ in range(4): G = [[G[h][~ w] for h in range(3)] for w in range(3)] for i, (h, w) in enumerate([(h, w) for h in range(3) for w in range(3)]): if G[h][w] == 1: break H = [] for x in range(3): for y in range(3): if G[x][y] == 1: H.append((x - h, y - w)) block.append(H) return block block = make_valid() #非再帰DFSで全列挙 左上詰で置いたときに最初の空きマスが(h, w)で、block[t]を置く予定 G = [[0] * W for _ in range(H)] stack = [(0, 0, t) for t in range(8)] d = 0 #再帰の深さ while stack: h, w, t = stack.pop() if h >= 0: #行きがけの処理 #1. 実際に置けるか判定。置けないならcontinue 置けるなら実際に配置 if not all( (x := h + p) in range(H) and (y := w + q) in range(W) and G[x][y] == 0 for p, q in block[t] ): continue d += 1 stack.append((~ h, w, t)) for p, q in block[t]: assert G[ x := h + p ][ y := w + q ] == 0 G[x][y] = d #2. 次の探索へ a = h * W + w for a in range(a + 1, H * W + 1): if a == H * W: break x, y = a // W, a % W if G[x][y] == 0: break if a == H * W: #完全に置き切れた場合 assert all( G[h][w] > 0 for h in range(H) for w in range(W) ), str(G) return G x, y = a // W, a % W for u in range(8): stack.append((x, y, u)) else: #帰りがけの処理 h = ~ h #1. 既に置いた石を除去 for p, q in block[t]: assert G[ x := h + p ][ y := w + q ] == d G[x][y] = 0 d -= 1 else: #だめでした return G #H, Wのうち、Hが偶数になるように適宜変更する。 #H ≡ 0 mod 8: W >= 2で常に可能。(8, 2), (8, 3)の構築を並べる #H ≡ 4 mod 8: Wが偶数なら可能。(4, 2)を並べる #H ≡ 2, 6 mod 8: Wが4の倍数なら可能。(W, H)を90度回転させる #結局 (4, 2), (8, 2), (8, 3)を使って構築すればよいと分かる tiles = [[None] * 9 for _ in range(9)] for h, w in [(4, 2), (8, 2), (8, 3)]: tiles[h][w] = brute(h, w) def rotate(G): if len(G) == 0: return [] else: return [[G[h][~ w] for h in range( len(G) )] for w in range( len(G[0]) )] def solve(H, W): if H & 1 == W & 1 == 1: return [] if H & 1: return rotate( solve(W, H) ) #1. H ≡ 0 mod 8 を構築する if H % 8 == 0: if W == 1: return [] G = [[0] * W for _ in range(H)] offset = 0 #既に置いた値 for h in range(0, H, 8): if W & 1: #(8, 3)構築を置く base = tiles[8][3] for x in range(8): for y in range(3): G[h + x][0 + y] = base[x][y] + offset offset += 6 for w in range( (3 if W & 1 else 0), W - 1, 2 ): base = tiles[8][2] for x in range(8): for y in range(2): G[h + x][w + y] = base[x][y] + offset offset += 4 return G #2. H ≡ 4 mod 8 を構築する if H % 8 == 4: if W & 1 == 1: return [] G = [[0] * W for _ in range(H)] offset = 0 base = tiles[4][2] for h in range(0, H, 4): for w in range(0, W, 2): for x in range(4): for y in range(2): G[h + x][w + y] = base[x][y] + offset offset += 2 return G #3. H ≡ 2, 6 mod 8 を構築する if H % 8 in [2, 6]: return rotate( solve(W, H) ) if W % 4 == 0 else [] return [] #実行 エスパーしたけどおもしろかった for _ in range( T := int(input()) ): H, W = map(int, input().split()) G = solve(H, W) if G == []: print(-1) else: print(H * W // 4) for h in range(H): print(*G[h])