This is the hard version of the problem. The difference between the versions is in the number of possible operations that can be made. You can make hacks if and only if you solved both versions of the problem.

You are given a binary table of size n × m. This table consists of symbols 0 and 1.

You can make such operation: select 3 different cells that belong to one 2 × 2 square and change the symbols in these cells (change 0 to 1 and 1 to 0).

Your task is to make all symbols in the table equal to 0. You are allowed to make at most nm operations. You don't need to minimize the number of operations.

It can be proved, that it is always possible.

Input

The first line contains a single integer t (1 ≤ t ≤ 5000) — the number of test cases. The next lines contain descriptions of test cases.

The first line of the description of each test case contains two integers n, m (2 ≤ n, m ≤ 100).

Each of the next n lines contains a binary string of length m, describing the symbols of the next row of the table.

It is guaranteed, that the sum of nm for all test cases does not exceed 20000.

Output

For each test case print the integer k (0 ≤ k ≤ nm) — the number of operations.

In the each of the next k lines print 6 integers x_1, y_1, x_2, y_2, x_3, y_3 (1 ≤ x_1, x_2, x_3 ≤ n, 1 ≤ y_1, y_2, y_3 ≤ m) describing the next operation. This operation will be made with three cells (x_1, y_1), (x_2, y_2), (x_3, y_3). These three cells should be different. These three cells should belong to some 2 × 2 square.

Example

Input


5
2 2
10
11
3 3
011
101
110
4 4
1111
0110
0110
1111
5 5
01011
11001
00010
11011
10000
2 3
011
101


Output


1
1 1 2 1 2 2
2 
2 1 3 1 3 2
1 2 1 3 2 3
4
1 1 1 2 2 2 
1 3 1 4 2 3
3 2 4 1 4 2
3 3 4 3 4 4
4
1 2 2 1 2 2 
1 4 1 5 2 5 
4 1 4 2 5 1
4 4 4 5 3 4
2
1 3 2 2 2 3
1 2 2 1 2 2

Note

In the first test case, it is possible to make only one operation with cells (1, 1), (2, 1), (2, 2). After that, all symbols will be equal to 0.

In the second test case:

  * operation with cells (2, 1), (3, 1), (3, 2). After it the table will be: 
    
          
    011  
    001  
    000  
    

  * operation with cells (1, 2), (1, 3), (2, 3). After it the table will be: 
    
          
    000  
    000  
    000  
    




In the fifth test case:

  * operation with cells (1, 3), (2, 2), (2, 3). After it the table will be: 
    
          
    010  
    110  
    

  * operation with cells (1, 2), (2, 1), (2, 2). After it the table will be: 
    
          
    000  
    000

Difficulty: HARD
Tags: Greedy algorithms

Graph algorithms

Implementation

Constructive algorithms
Skill types: Greedy algorithms

Starter code:

Solutions:
import sys
input = sys.stdin.readline

def change(x1, x2, x3, y1, y2, y3, ll):
	ll[x1][y1] = 1 - ll[x1][y1]
	ll[x2][y2] = 1 - ll[x2][y2]
	ll[x3][y3] = 1 - ll[x3][y3]
t = int(input())
while t:
	(n, m) = map(int, input().split())
	ll = []
	for i in range(n):
		l = list(map(int, input().strip()))
		ll.append(l)
	ans = []
	for i in range(n - 1):
		for j in range(m):
			if i == n - 2 and j == m - 2:
				break
			if ll[i][j]:
				if j + 1 < m:
					ans.append((i + 1, i + 2, i + 2, j + 1, j + 1, j + 2))
					change(i, i + 1, i + 1, j, j, j + 1, ll)
				else:
					ans.append((i + 1, i + 2, i + 2, j + 1, j + 1, j))
					change(i, i + 1, i + 1, j, j, j - 1, ll)
	for i in range(m - 1):
		if ll[n - 1][i] and ll[n - 2][i]:
			ans.append((n - 1, n, n, i + 1, i + 1, i + 2))
			change(n - 2, n - 1, n - 1, i, i, i + 1, ll)
		elif ll[n - 1][i]:
			ans.append((n, n, n - 1, i + 1, i + 2, i + 2))
			change(n - 1, n - 1, n - 2, i, i + 1, i + 1, ll)
		elif ll[n - 2][i]:
			ans.append((n - 1, n - 1, n, i + 1, i + 2, i + 2))
			change(n - 2, n - 2, n - 1, i, i + 1, i + 1, ll)
	if ll[n - 1][m - 1] and ll[n - 2][m - 1]:
		ans.append((n, n - 1, n, m, m - 1, m - 1))
		ans.append((n, n - 1, n - 1, m - 1, m - 1, m))
	elif ll[n - 2][m - 1]:
		ans.append((n - 1, n, n, m, m, m - 1))
		change(n - 2, n - 1, n - 1, m - 1, m - 1, m - 2, ll)
		ans.append((n, n - 1, n - 1, m, m - 1, m))
		change(n - 1, n - 2, n - 2, m - 1, m - 2, m - 1, ll)
		ans.append((n, n - 1, n - 1, m - 1, m, m - 1))
		change(n - 1, n - 2, n - 2, m - 2, m - 1, m - 2, ll)
	elif ll[n - 1][m - 1]:
		ans.append((n, n, n - 1, m, m - 1, m - 1))
		ans.append((n - 1, n - 1, n, m - 1, m, m))
		ans.append((n, n, n - 1, m - 1, m, m))
	print(len(ans))
	for i in ans:
		(x1, x2, x3, y1, y2, y3) = i
		print(x1, y1, x2, y2, x3, y3)
	t -= 1


import sys
Z = sys.stdin.readline
O = []

def S(q, x, y):
	s = sum((sum(i) for i in q))
	v = [(x, y, x + 1, y, x, y + 1), (x, y, x + 1, y + 1, x, y + 1), (x, y, x + 1, y, x + 1, y + 1), (x + 1, y + 1, x + 1, y, x, y + 1)]
	if s > 3:
		return v
	if s > 2:
		if q[0][0] < 1:
			return [v[3]]
		if q[0][1] < 1:
			return [v[2]]
		if q[1][0] < 1:
			return [v[1]]
		return [v[0]]
	if s > 1:
		if q[0][0] < 1 and q[0][1] < 1:
			return v[:2]
		if q[0][0] < 1 and q[1][1] < 1:
			return v[1:3]
		if q[0][0] < 1 and q[1][0] < 1:
			return [v[0], v[2]]
		if q[0][1] < 1 and q[1][1] < 1:
			return [v[1], v[3]]
		if q[0][1] < 1 and q[1][0] < 1:
			return [v[0], v[3]]
		if q[1][0] < 1 and q[1][1] < 1:
			return v[2:]
	if s:
		if q[0][0]:
			k = 3
		elif q[0][1]:
			k = 2
		elif q[1][0]:
			k = 1
		else:
			k = 0
		return v[:k] + v[k + 1:]
	return []
for _ in range(int(Z())):
	(n, m) = map(int, Z().split())
	a = []
	o = []
	for i in range(n):
		a.append(list(map(int, Z().strip())))
	if n % 2:
		for i in range(0, m - m % 2, 2):
			if a[-1][i]:
				if a[-1][i + 1]:
					o += [(n, i + 1, n, i + 2, n - 1, i + 1)]
					a[-2][i] = 1 - a[-2][i]
				else:
					o += [(n, i + 1, n - 1, i + 2, n - 1, i + 1)]
					a[-2][i] = 1 - a[-2][i]
					a[-2][i + 1] = 1 - a[-2][i + 1]
			elif a[-1][i + 1]:
				o += [(n, i + 2, n - 1, i + 2, n - 1, i + 1)]
				a[-2][i] = 1 - a[-2][i]
				a[-2][i + 1] = 1 - a[-2][i + 1]
		if m % 2 and a[-1][-1]:
			o += [(n, m, n - 1, m, n - 1, m - 1)]
			a[-2][-1] = 1 - a[-2][-1]
			a[-2][-2] = 1 - a[-2][-2]
	if m % 2:
		for i in range(0, n - n % 2, 2):
			if a[i][-1]:
				if a[i + 1][-1]:
					o += [(i + 1, m, i + 2, m, i + 1, m - 1)]
					a[i][-2] = 1 - a[i][-2]
				else:
					o += [(i + 1, m, i + 2, m - 1, i + 1, m - 1)]
					a[i][-2] = 1 - a[i][-2]
					a[i + 1][-2] = 1 - a[i + 1][-2]
			elif a[i + 1][-1]:
				o += [(i + 2, m - 1, i + 2, m, i + 1, m - 1)]
				a[i][-2] = 1 - a[i][-2]
				a[i + 1][-2] = 1 - a[i + 1][-2]
	for i in range(n // 2):
		for j in range(m // 2):
			(x, y) = (2 * i, 2 * j)
			o += S(((a[x][y], a[x][y + 1]), (a[x + 1][y], a[x + 1][y + 1])), x + 1, y + 1)
	O.append(str(len(o)))
	O.append('\n'.join((' '.join(map(str, i)) for i in o)))
print('\n'.join(O))


from __future__ import division, print_function
import os
import sys
from io import BytesIO, IOBase
if sys.version_info[0] < 3:
	from __builtin__ import xrange as range
	from future_builtins import ascii, filter, hex, map, oct, zip

def main():
	t = int(input())

	def make_op(table, op):
		table[op[0]][op[1]] = 1 - table[op[0]][op[1]]
		table[op[2]][op[3]] = 1 - table[op[2]][op[3]]
		table[op[4]][op[5]] = 1 - table[op[4]][op[5]]
	for _ in range(t):
		(n, m) = map(int, input().split())
		table = [list(map(int, input())) for _ in range(n)]
		ops = []
		for i in range(0, n - 1, 2):
			for j in range(m - 1):
				if table[i][j] and table[i + 1][j]:
					op = [i, j, i + 1, j, i, j + 1]
					ops.append(op)
					make_op(table, op)
				elif table[i][j]:
					op = [i, j, i, j + 1, i + 1, j + 1]
					ops.append(op)
					make_op(table, op)
				elif table[i + 1][j]:
					op = [i + 1, j, i, j + 1, i + 1, j + 1]
					ops.append(op)
					make_op(table, op)
		i = n - 2
		for j in range(m - 1):
			if table[i][j] and table[i + 1][j]:
				op = [i, j, i + 1, j, i, j + 1]
				ops.append(op)
				make_op(table, op)
			elif table[i][j]:
				op = [i, j, i, j + 1, i + 1, j + 1]
				ops.append(op)
				make_op(table, op)
			elif table[i + 1][j]:
				op = [i + 1, j, i, j + 1, i + 1, j + 1]
				ops.append(op)
				make_op(table, op)
		j = m - 2
		for i in range(n - 2):
			if table[i][j] and table[i][j + 1]:
				op = [i, j, i, j + 1, i + 1, j]
				ops.append(op)
				make_op(table, op)
			elif table[i][j]:
				op = [i, j, i + 1, j, i + 1, j + 1]
				ops.append(op)
				make_op(table, op)
			elif table[i][j + 1]:
				op = [i, j + 1, i + 1, j, i + 1, j + 1]
				ops.append(op)
				make_op(table, op)
		while True:
			ones = []
			zeros = []
			for i in range(n - 2, n):
				for j in range(m - 2, m):
					if table[i][j]:
						ones.append([i, j])
					else:
						zeros.append([i, j])
			if len(ones) == 0:
				break
			elif len(ones) <= 2:
				op = [*ones.pop(), *zeros.pop(), *zeros.pop()]
				ops.append(op)
				make_op(table, op)
			elif len(ones) >= 3:
				op = [*ones.pop(), *ones.pop(), *ones.pop()]
				ops.append(op)
				make_op(table, op)
		assert len(ops) <= n * m
		print(len(ops))
		for op in ops:
			print(*[i + 1 for i in op])
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import os
from io import BytesIO, IOBase
import sys
from collections import defaultdict, deque, Counter
from bisect import *
from math import sqrt, pi, ceil, log, inf, gcd, floor
from itertools import permutations
from copy import deepcopy
from heapq import *

def lcm(a, b):
	return a * b // gcd(a, b)

def main():
	for _ in range(int(input())):
		(n, m) = map(int, input().split())
		a = []
		for i in range(n):
			a.append(list(map(int, input().rstrip())))
		b = []
		for i in range(n - 1):
			for j in range(m):
				if j != m - 1:
					if a[i][j] == 1:
						b.extend([[i, j], [i + 1, j], [i + 1, j + 1]])
						a[i][j] = int(not a[i][j])
						a[i + 1][j] = int(not a[i + 1][j])
						a[i + 1][j + 1] = int(not a[i + 1][j + 1])
				elif a[i][j] == 1:
					b.extend([[i, j], [i + 1, j], [i + 1, j - 1]])
					a[i][j] = int(not a[i][j])
					a[i + 1][j] = int(not a[i + 1][j])
					a[i + 1][j - 1] = int(not a[i + 1][j - 1])
		i = n - 1
		x = 0
		for j in range(m - 2):
			if a[i][j] == 1 or a[i - 1][j] == 1:
				if a[i][j] == 1 and a[i - 1][j] == 1:
					b.extend([[i, j], [i - 1, j]])
					a[i][j] = int(not a[i][j])
					a[i - 1][j] = int(not a[i - 1][j])
				elif a[i][j] == 1:
					b.extend([[i, j], [i - 1, j + 1]])
					a[i][j] = int(not a[i][j])
					a[i - 1][j + 1] = int(not a[i - 1][j + 1])
				else:
					b.extend([[i - 1, j], [i - 1, j + 1]])
					a[i - 1][j] = int(not a[i - 1][j])
					a[i - 1][j + 1] = int(not a[i - 1][j + 1])
				b.append([i, j + 1])
				a[i][j + 1] = int(not a[i][j + 1])
				x += 1
		z = (a[-1][-1] == 0) + (a[-1][-2] == 0) + (a[-2][-1] == 0) + (a[-2][-2] == 0)
		f = 0
		if z == 3 and len(b) // 3 == n * m - 2:
			f = 1
			b[-3 * (x + 2)] = [-1, -1]
			a[-2][-2] = int(not a[-2][-2])
			a[-1][-2] = int(not a[-1][-2])
			a[-1][-1] = int(not a[-1][-1])
		z = (a[-1][-1] == 0) + (a[-1][-2] == 0) + (a[-2][-1] == 0) + (a[-2][-2] == 0)
		if z == 1:
			b.extend([[n - 1, m - 1], [n - 1, m - 2], [n - 2, m - 2]])
		elif z == 2 or z == 3:
			if z == 3:
				a[n - 1][m - 2] = int(not a[n - 1][m - 2])
				a[n - 1][m - 1] = int(not a[n - 1][m - 1])
				a[n - 2][m - 2] = int(not a[n - 2][m - 2])
				b.extend([[n - 2, m - 2], [n - 1, m - 2], [n - 1, m - 1]])
			if a[-2][-2] == 0:
				b.extend([[n - 2, m - 2], [n - 2, m - 1], [n - 1, m - 2], [n - 1, m - 1], [n - 2, m - 2], [n - 2, m - 1]])
			elif a[-1][-2] == 0:
				b.extend([[n - 2, m - 2], [n - 1, m - 2], [n - 2, m - 1], [n - 1, m - 1], [n - 1, m - 2], [n - 2, m - 1]])
			elif a[-1][-1] == 0:
				b.extend([[n - 2, m - 1], [n - 1, m - 1], [n - 2, m - 2], [n - 1, m - 1], [n - 2, m - 1], [n - 1, m - 2]])
		print(len(b) // 3 - f)
		for i in range(0, len(b), 3):
			if b[i][0] != -1:
				print(b[i][0] + 1, b[i][1] + 1, b[i + 1][0] + 1, b[i + 1][1] + 1, b[i + 2][0] + 1, b[i + 2][1] + 1)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import copy

def two_two_solver(mat, i, j, ans):
	oneind = []
	zeroind = []
	for x in range(i, i + 2):
		for y in range(j, j + 2):
			if mat[x][y] == '1':
				oneind += [[x, y]]
			else:
				zeroind += [[x, y]]
	if len(oneind) == 0:
		return
	if len(oneind) == 4:
		newoneind = [oneind[0][:]]
		newzeroind = [oneind[1][:], oneind[2][:], oneind[3][:]]
		ans += [[oneind[1][:], oneind[2][:], oneind[3][:]]]
		oneind = copy.deepcopy(newoneind)
		zeroind = copy.deepcopy(newzeroind)
	if len(oneind) == 1:
		newoneind = [zeroind[0][:], zeroind[1][:]]
		newzeroind = [zeroind[2][:], oneind[0][:]]
		ans += [[zeroind[0][:], zeroind[1][:], oneind[0][:]]]
		oneind = copy.deepcopy(newoneind)
		zeroind = copy.deepcopy(newzeroind)
	if len(oneind) == 2:
		newoneind = [zeroind[0][:], zeroind[1][:], oneind[0][:]]
		newzeroind = [oneind[1][:]]
		ans += [[zeroind[0][:], zeroind[1][:], oneind[1][:]]]
		oneind = copy.deepcopy(newoneind)
		zeroind = copy.deepcopy(newzeroind)
	if len(oneind) == 3:
		ans += [[oneind[0][:], oneind[1][:], oneind[2][:]]]
	for x in range(i, i + 2):
		for y in range(j, j + 2):
			mat[x][y] = '0'

def three_two_solver(mat, i, j, ans):
	oneind = []
	zeroind = []
	for x in range(i, i + 2):
		for y in range(j, j + 2):
			if mat[x][y] == '1':
				oneind += [[x, y]]
			else:
				zeroind += [[x, y]]
	oneind2 = []
	zeroind2 = []
	for x in range(i, i + 2):
		for y in range(j + 1, j + 3):
			if mat[x][y] == '1':
				oneind2 += [[x, y]]
			else:
				zeroind2 += [[x, y]]
	if len(oneind2) < len(oneind):
		two_two_solver(mat, i, j + 1, ans)
		oneind = []
		zeroind = []
		for x in range(i, i + 2):
			for y in range(j, j + 2):
				if mat[x][y] == '1':
					oneind += [[x, y]]
				else:
					zeroind += [[x, y]]
		two_two_solver(mat, i, j, ans)
	else:
		two_two_solver(mat, i, j, ans)
		oneind2 = []
		zeroind2 = []
		for x in range(i, i + 2):
			for y in range(j + 1, j + 3):
				if mat[x][y] == '1':
					oneind2 += [[x, y]]
				else:
					zeroind2 += [[x, y]]
		two_two_solver(mat, i, j + 1, ans)

def two_three_solver(mat, i, j, ans):
	oneind = []
	zeroind = []
	for x in range(i, i + 2):
		for y in range(j, j + 2):
			if mat[x][y] == '1':
				oneind += [[x, y]]
			else:
				zeroind += [[x, y]]
	oneind2 = []
	zeroind2 = []
	for x in range(i + 1, i + 3):
		for y in range(j, j + 2):
			if mat[x][y] == '1':
				oneind2 += [[x, y]]
			else:
				zeroind2 += [[x, y]]
	if len(oneind2) < len(oneind):
		two_two_solver(mat, i + 1, j, ans)
		oneind = []
		zeroind = []
		for x in range(i, i + 2):
			for y in range(j, j + 2):
				if mat[x][y] == '1':
					oneind += [[x, y]]
				else:
					zeroind += [[x, y]]
		two_two_solver(mat, i, j, ans)
	else:
		two_two_solver(mat, i, j, ans)
		oneind2 = []
		zeroind2 = []
		for x in range(i + 1, i + 3):
			for y in range(j, j + 2):
				if mat[x][y] == '1':
					oneind2 += [[x, y]]
				else:
					zeroind2 += [[x, y]]
		two_two_solver(mat, i + 1, j, ans)
t = int(input())
for _ in range(t):
	(n, m) = map(int, input().split())
	mat = []
	for i in range(n):
		s = input()
		mat += [[x for x in s]]
	ans = []
	if n % 2 == 0 and m % 2 == 0:
		for i in range(0, n - 1, 2):
			for j in range(0, m - 1, 2):
				two_two_solver(mat, i, j, ans)
	elif n % 2 == 0 and m % 2 == 1:
		for i in range(0, n - 1, 2):
			for j in range(0, m - 3, 2):
				two_two_solver(mat, i, j, ans)
			three_two_solver(mat, i, m - 3, ans)
	elif n % 2 == 1 and m % 2 == 0:
		for i in range(0, n - 3, 2):
			for j in range(0, m - 1, 2):
				two_two_solver(mat, i, j, ans)
		for j in range(0, m - 1, 2):
			two_three_solver(mat, n - 3, j, ans)
	else:
		if mat[n - 1][m - 1] == '1':
			ans += [[[n - 1, m - 1], [n - 2, m - 1], [n - 1, m - 2]]]
			mat[n - 1][m - 1] = '0'
			if mat[n - 2][m - 1] == '1':
				mat[n - 2][m - 1] = '0'
			else:
				mat[n - 2][m - 1] = '1'
			if mat[n - 1][m - 2] == '1':
				mat[n - 1][m - 2] = '0'
			else:
				mat[n - 1][m - 2] = '1'
		if mat[n - 1][m - 2] == '1':
			ans += [[[n - 1, m - 2], [n - 2, m - 2], [n - 1, m - 3]]]
			mat[n - 1][m - 2] = '0'
			if mat[n - 2][m - 2] == '1':
				mat[n - 2][m - 2] = '0'
			else:
				mat[n - 2][m - 2] = '1'
			if mat[n - 1][m - 3] == '1':
				mat[n - 1][m - 3] = '0'
			else:
				mat[n - 1][m - 3] = '1'
		if mat[n - 1][m - 3] == '1':
			ans += [[[n - 1, m - 3], [n - 2, m - 3], [n - 2, m - 2]]]
			mat[n - 1][m - 3] = '0'
			if mat[n - 2][m - 3] == '1':
				mat[n - 2][m - 3] = '0'
			else:
				mat[n - 2][m - 3] = '1'
			if mat[n - 2][m - 2] == '1':
				mat[n - 2][m - 2] = '0'
			else:
				mat[n - 2][m - 2] = '1'
		for i in range(0, n - 3, 2):
			for j in range(0, m - 3, 2):
				two_two_solver(mat, i, j, ans)
		for i in range(0, n - 1, 2):
			three_two_solver(mat, i, m - 3, ans)
		for j in range(0, m - 1, 2):
			two_three_solver(mat, n - 3, j, ans)
	print(len(ans))
	for x in ans:
		for y in x:
			print(y[0] + 1, y[1] + 1, end=' ')
		print('')


import io, os
from math import *
J = input
input = lambda : J().encode()
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
for _ in range(int(input())):
	(n, m) = map(int, input().split())
	a = [[0 if c == ord('0') else 1 for c in input()] for _ in range(n)]
	r = []
	i = j = 0
	amt = 0
	z = []
	o = []
	t = []

	def calc():
		global r, t, amt, z, o
		t = [a[i][j], a[i][j + 1], a[i + 1][j], a[i + 1][j + 1]]
		amt = t.count(1)
		z = [x for x in range(4) if t[x] == 0]
		o = [x for x in range(4) if t[x] == 1]

	def do(m):
		global r, t, amt, z, o
		r += [m]
		(x1, y1, x2, y2, x3, y3) = m
		a[x1 - 1][y1 - 1] ^= 1
		a[x2 - 1][y2 - 1] ^= 1
		a[x3 - 1][y3 - 1] ^= 1
		calc()
	UR = lambda : do([i + 1, j + 1, i + 1, j + 2, i + 2, j + 2])
	UL = lambda : do([i + 1, j + 1, i + 1, j + 2, i + 2, j + 1])
	LR = lambda : do([i + 1, j + 2, i + 2, j + 1, i + 2, j + 2])
	LL = lambda : do([i + 1, j + 1, i + 2, j + 1, i + 2, j + 2])
	calc()
	if n % 2 == 1:
		i = n - 2
		for j in range(0, m, 2):
			j = min(j, m - 2)
			b = [a[i + 1][j], a[i + 1][j + 1]]
			if b == [1, 0]:
				UL()
			elif b == [0, 1]:
				UR()
			elif b == [1, 1]:
				LL()
	if m % 2 == 1:
		j = m - 2
		for i in range(0, n - 1, 2):
			b = [a[i][j + 1], a[i + 1][j + 1]]
			if b == [1, 0]:
				UL()
			elif b == [0, 1]:
				LL()
			elif b == [1, 1]:
				UR()
	for i in range(0, n - 1, 2):
		for j in range(0, m - 1, 2):
			t = [a[i][j], a[i][j + 1], a[i + 1][j], a[i + 1][j + 1]]
			amt = t.count(1)
			z = [x for x in range(4) if t[x] == 0]
			o = z = [x for x in range(4) if t[x] == 1]

			def do(m):
				global r, t, amt, z, o
				r += [m]
				(x1, y1, x2, y2, x3, y3) = m
				a[x1 - 1][y1 - 1] ^= 1
				a[x2 - 1][y2 - 1] ^= 1
				a[x3 - 1][y3 - 1] ^= 1
				t = [a[i][j], a[i][j + 1], a[i + 1][j], a[i + 1][j + 1]]
				amt = t.count(1)
				z = [x for x in range(4) if t[x] == 0]
				o = [x for x in range(4) if t[x] == 1]
			z = [x for x in range(4) if t[x] == 0]
			if amt == 4:
				LR()
			if amt == 1:
				[UL, UR, LL, LR][o[0]]()
			if amt == 2:
				[LR, LL, UR, UL][o[0]]()
			if amt == 3:
				[LR, LL, UR, UL][z[0]]()
	print(len(r))
	for x in r:
		print(*x)


import sys
input = sys.stdin.readline
for _ in range(int(input())):
	(n, m) = list(map(int, input().split()))
	arr = []
	ans = []
	for i in range(n):
		arr.append([])
		temp = input().rstrip()
		for char in temp:
			if char == '1':
				arr[i].append(True)
			else:
				arr[i].append(False)
	for i in range(n - 1, 1, -1):
		for j in range(m):
			if arr[i][j]:
				if j == m - 1:
					arr[i][j] = not arr[i][j]
					arr[i - 1][j] = not arr[i - 1][j]
					arr[i - 1][j - 1] = not arr[i - 1][j - 1]
					ans.append((i, j, i - 1, j, i - 1, j - 1))
				else:
					arr[i][j] = not arr[i][j]
					arr[i - 1][j] = not arr[i - 1][j]
					arr[i - 1][j + 1] = not arr[i - 1][j + 1]
					ans.append((i, j, i - 1, j, i - 1, j + 1))
	if m & 1:
		if arr[0][m - 1]:
			arr[0][m - 1] = not arr[0][m - 1]
			arr[0][m - 2] = not arr[0][m - 2]
			arr[1][m - 2] = not arr[1][m - 2]
			ans.append((0, m - 1, 0, m - 2, 1, m - 2))
		if arr[1][m - 1]:
			arr[1][m - 1] = not arr[1][m - 1]
			arr[1][m - 2] = not arr[1][m - 2]
			arr[0][m - 2] = not arr[0][m - 2]
			ans.append((1, m - 1, 1, m - 2, 0, m - 2))
	for i in range(0, m - 1, 2):
		count1 = 0
		ones = []
		for x in range(2):
			for y in range(2):
				if arr[y][i + x]:
					ones.append((y, i + x))
					count1 += 1
		if count1 == 0:
			pass
		if count1 == 1:
			x = ones[0][0]
			y = ones[0][1]
			count1 = 2
			ans.append((x, y, x ^ 1, y, x, y ^ 1))
			ones = [(x ^ 1, y), (x, y ^ 1)]
			arr[x][y] = not arr[x][y]
			arr[x ^ 1][y] = not arr[x ^ 1][y]
			arr[x][y ^ 1] = not arr[x][y ^ 1]
		if count1 == 2:
			if ones[0][0] == ones[1][0] or ones[0][1] == ones[1][1]:
				ones = [(ones[0][0] ^ 1, ones[0][1] ^ 1), (ones[1][0] ^ 1, ones[1][1] ^ 1)]
			for one in ones:
				x = one[0]
				y = one[1]
				arr[x][y] = not arr[x][y]
				arr[x ^ 1][y] = not arr[x ^ 1][y]
				arr[x][y ^ 1] = not arr[x][y ^ 1]
				ans.append((x, y, x ^ 1, y, x, y ^ 1))
		if count1 == 3:
			arr[ones[0][0]][ones[0][1]] = not arr[ones[0][0]][ones[0][1]]
			arr[ones[1][0]][ones[1][1]] = not arr[ones[1][0]][ones[1][1]]
			arr[ones[2][0]][ones[2][1]] = not arr[ones[2][0]][ones[2][1]]
			ans.append((ones[0][0], ones[0][1], ones[1][0], ones[1][1], ones[2][0], ones[2][1]))
		if count1 == 4:
			for x in range(2):
				for y in range(2):
					arr[x][y + i] = not arr[x][y + i]
					arr[x ^ 1][y + i] = not arr[x ^ 1][y + i]
					arr[x][y ^ 1 + i] = not arr[x][y ^ 1 + i]
					ans.append((x, y + i, x ^ 1, y + i, x, y ^ 1 + i))
	print(len(ans))
	for move in ans:
		for ele in move:
			print(ele + 1, end=' ')
		print()


import sys, os
import heapq, functools, collections
import math, random
from collections import Counter, defaultdict

def solve_(g, n, m):
	og = [[x for x in row] for row in grid]
	(x, y) = (0, 0)
	res = []
	for y in range(n - 2):
		for x in range(m - 1):
			if g[y][x] == 0:
				continue
			if g[y][x] == 1 and g[y][x + 1] == 1:
				if g[y + 1][x] == 1:
					r = [(y, x), (y, x + 1), (y + 1, x)]
				else:
					r = [(y, x), (y, x + 1), (y + 1, x + 1)]
			if g[y][x] == 1 and g[y][x + 1] == 0:
				r = [(y, x), (y + 1, x), (y + 1, x + 1)]
			assert len(r) == 3
			assert len(set(r)) == 3
			res.append(r)
			for (yy, xx) in r:
				g[yy][xx] = 1 - g[yy][xx]
		assert x + 1 == m - 1
		if g[y][x] == 0 and g[y][x + 1] == 0:
			continue
		elif g[y][x] == 1 and g[y][x + 1] == 0:
			r = [(y, x), (y + 1, x), (y + 1, x + 1)]
		elif g[y][x] == 0 and g[y][x + 1] == 1:
			r = [(y, x + 1), (y + 1, x), (y + 1, x + 1)]
		elif g[y][x] == 1 and g[y][x + 1] == 1:
			r = [(y, x), (y, x + 1), (y + 1, x)]
		assert len(r) == 3
		assert len(set(r)) == 3
		res.append(r)
		for (yy, xx) in r:
			g[yy][xx] = 1 - g[yy][xx]
	for x in range(m - 2):
		if g[-2][x] == 0 and g[-1][x] == 0:
			continue
		if g[-2][x] == 1 and g[-1][x] == 0:
			r = [(-2, x), (-2, x + 1), (-1, x + 1)]
		if g[-2][x] == 0 and g[-1][x] == 1:
			r = [(-1, x), (-2, x + 1), (-1, x + 1)]
		if g[-2][x] == 1 and g[-1][x] == 1:
			if g[-2][x + 1] == 1:
				r = [(-2, x), (-1, x), (-2, x + 1)]
			else:
				r = [(-2, x), (-1, x), (-1, x + 1)]
		assert len(r) == 3
		assert len(set(r)) == 3
		res.append(r)
		for (yy, xx) in r:
			g[yy][xx] = 1 - g[yy][xx]
	l4 = [(-2, -2), (-2, -1), (-1, -2), (-1, -1)]
	if g[-2][-2] + g[-2][-1] + g[-1][-2] + g[-1][-1] == 4:
		console('resolve 4')
		r = l4[:3]
		assert len(r) == 3
		assert len(set(r)) == 3
		res.append(r)
		for (yy, xx) in r:
			g[yy][xx] = 1 - g[yy][xx]
	if g[-2][-2] + g[-2][-1] + g[-1][-2] + g[-1][-1] == 1:
		console('resolve 1')
		for (i, (y, x)) in enumerate(l4 + l4):
			if g[y][x] == 1:
				r = (l4 + l4)[i:i + 3]
				break
		assert len(r) == 3
		assert len(set(r)) == 3
		res.append(r)
		for (yy, xx) in r:
			g[yy][xx] = 1 - g[yy][xx]
	if g[-2][-2] + g[-2][-1] + g[-1][-2] + g[-1][-1] == 2:
		console('resolve 2')
		sett = set()
		for (i, (y, x)) in enumerate(l4 + l4 + l4):
			if g[y][x] == 0:
				sett.add((y, x))
			if len(sett) == 2:
				sett.add((y, x))
			if len(sett) == 3:
				break
		r = list(sett)
		assert len(r) == 3
		assert len(set(r)) == 3
		res.append(r)
		for (yy, xx) in r:
			g[yy][xx] = 1 - g[yy][xx]
	if g[-2][-2] + g[-2][-1] + g[-1][-2] + g[-1][-1] == 3:
		console('resolve 3')
		r = []
		for (i, (y, x)) in enumerate(l4):
			if g[y][x] == 1:
				r.append((y, x))
		assert len(r) == 3
		assert len(set(r)) == 3
		res.append(r)
		for (yy, xx) in r:
			g[yy][xx] = 1 - g[yy][xx]
	res2 = []
	for re in res:
		re2 = []
		for (a, b) in re:
			if a < 0:
				a = n + a
			if b < 0:
				b = m + b
			re2.extend((a + 1, b + 1))
		res2.append(re2)
	assert sum((sum(row) for row in grid)) == 0
	for (x1, y1, x2, y2, x3, y3) in res2:
		(x1, y1, x2, y2, x3, y3) = (x1 - 1, y1 - 1, x2 - 1, y2 - 1, x3 - 1, y3 - 1)
		og[x1][y1] = 1 - og[x1][y1]
		og[x2][y2] = 1 - og[x2][y2]
		og[x3][y3] = 1 - og[x3][y3]
	assert sum((sum(row) for row in og)) == 0
	assert len(res2) <= n * m
	return res2

def console(*args):
	print('\x1b[36m', *args, '\x1b[0m', file=sys.stderr)
	pass
ONLINE_JUDGE = False
if os.path.exists('input.txt'):
	ONLINE_JUDGE = True
if ONLINE_JUDGE:
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')

	def console(*args):
		pass

def solve(*args):
	if not ONLINE_JUDGE:
		console('----- solving ------')
		console(*args)
		console('----- ------- ------')
	return solve_(*args)
if True:
	inp = iter(sys.stdin.readlines())
	input = lambda : next(inp)
else:
	input = sys.stdin.readline
for case_num in range(int(input())):
	(n, m) = list(map(int, input().split()))
	grid = []
	for _ in range(n):
		grid.append(list(map(int, list(input().strip()))))
	res = solve(grid, n, m)
	print(len(res))
	for r in res:
		print(*r)


def unique_pairs(n):
	for i in range(n):
		for j in range(n):
			yield (i, j)

def oper1(table, n, m, res):
	for i in range(n - 1, 1, -1):
		for j in range(m - 2):
			if table[i][j] == 1:
				res.append([i, j, i - 1, j, i - 1, j + 1])
				table[i - 1][j] ^= 1
				table[i - 1][j + 1] ^= 1
		if table[i][m - 1] == table[i][m - 2] == 1:
			res.append([i, m - 1, i, m - 2, i - 1, m - 1])
			table[i - 1][m - 1] ^= 1
		elif table[i][m - 1]:
			res.append([i, m - 1, i - 1, m - 1, i - 1, m - 2])
			table[i - 1][m - 1] ^= 1
			table[i - 1][m - 2] ^= 1
		elif table[i][m - 2]:
			res.append([i, m - 2, i - 1, m - 2, i - 1, m - 1])
			table[i - 1][m - 1] ^= 1
			table[i - 1][m - 2] ^= 1
		table = table[:-1]
	return (table, res)

def oper2(table, m, res):
	for j in range(m - 1, 1, -1):
		if table[0][j] == table[1][j] == 1:
			res.append([0, j, 1, j, 0, j - 1])
			table[0][j - 1] ^= 1
		elif table[0][j]:
			res.append([0, j, 0, j - 1, 1, j - 1])
			table[0][j - 1] ^= 1
			table[1][j - 1] ^= 1
		elif table[1][j]:
			res.append([1, j, 0, j - 1, 1, j - 1])
			table[0][j - 1] ^= 1
			table[1][j - 1] ^= 1
	return (table, res)

def solve(t, n, m):
	res = []
	if n > 2:
		(t, res) = oper1(t, n, m, res)
	if m > 2:
		(t, res) = oper2(t, m, res)
		t = [i[:2] for i in t]
	cnt1 = sum((x.count(1) for x in t))
	if cnt1:
		if cnt1 == 4:
			res.append([0, 1, 1, 1, 1, 0])
			t = [[1, 0], [0, 0]]
			cnt1 -= 3
		if cnt1 == 1:
			for (i, j) in unique_pairs(2):
				if t[i][j] == 1:
					res.append([i, j, i ^ 1, j, i ^ 1, j ^ 1])
					(t[i][j], t[i ^ 1][j], t[i ^ 1][j ^ 1]) = (0, 1, 1)
					break
			cnt1 += 1
		if cnt1 == 2:
			cnt = 0
			qwq = []
			for (i, j) in unique_pairs(2):
				if t[i][j] == 0:
					qwq.extend([i, j])
					t[i][j] = 1
				elif not cnt:
					qwq.extend([i, j])
					cnt += 1
					t[i][j] = 0
			res.append(qwq)
			cnt1 += 1
		if cnt1 == 3:
			for (i, j) in unique_pairs(2):
				if not t[i][j]:
					res.append([i, j ^ 1, i ^ 1, j ^ 1, i ^ 1, j])
					break
	print(len(res))
	res = [[j + 1 for j in i] for i in res]
	for _ in res:
		print(*_)
for _ in range(int(input())):
	(n, m) = map(int, input().split())
	table = []
	for i in range(n):
		table.append([int(i) for i in list(input())])
	solve(table, n, m)


import sys

def printm():
	for row in M:
		print(''.join(map(str, row)))

def change1(i, j):
	if i:
		di = -1
	else:
		di = 1
	if j:
		dj = -1
	else:
		dj = 1
	out = []
	out.append((i, j, i + di, j, i + di, j + dj))
	out.append((i, j, i, j + dj, i + di, j + dj))
	out.append((i, j, i + di, j, i, j + dj))
	return out

def change3(i, j, pos):
	if pos == 0:
		return [(i, j + 1, i + 1, j, i + 1, j + 1)]
	if pos == 1:
		return [(i, j, i + 1, j, i + 1, j + 1)]
	if pos == 2:
		return [(i, j, i, j + 1, i + 1, j + 1)]
	if pos == 3:
		return [(i, j, i, j + 1, i + 1, j)]

def change2(i, j, pos):
	out = []
	if pos == 0:
		out.append((i, j, i + 1, j, i, j + 1))
		out.append((i + 1, j + 1, i + 1, j, i, j + 1))
	elif pos == 1:
		out.append((i, j, i, j + 1, i + 1, j + 1))
		out.append((i + 1, j, i, j, i + 1, j + 1))
	elif pos == 2:
		out.append((i, j, i, j + 1, i + 1, j + 1))
		out.append((i, j + 1, i + 1, j, i + 1, j + 1))
	elif pos == 3:
		out.append((i, j, i + 1, j, i, j + 1))
		out.append((i, j, i + 1, j, i + 1, j + 1))
	elif pos == 4:
		out.append((i, j, i + 1, j, i + 1, j + 1))
		out.append((i, j + 1, i + 1, j, i + 1, j + 1))
	elif pos == 5:
		out.append((i, j, i + 1, j, i, j + 1))
		out.append((i, j, i, j + 1, i + 1, j + 1))
	return out
t = int(input())
for _t in range(t):
	(n, m) = map(int, sys.stdin.readline().split())
	M = []
	out = []
	for i in range(n):
		M.append(list(map(int, list(sys.stdin.readline().strip()))))
	if n % 2:
		start_i = 1
		for j in range(m):
			if M[0][j]:
				if j == m - 1:
					M[0][j] = 0
					M[1][j] = 1 - M[1][j]
					M[1][j - 1] = 1 - M[1][j - 1]
					out.append((0, j, 1, j, 1, j - 1))
				elif M[0][j + 1]:
					M[0][j] = 0
					M[0][j + 1] = 0
					M[1][j] = 1 - M[1][j]
					out.append((0, j, 0, j + 1, 1, j))
				else:
					M[0][j] = 0
					M[1][j] = 1 - M[1][j]
					M[1][j + 1] = 1 - M[1][j + 1]
					out.append((0, j, 1, j, 1, j + 1))
	else:
		start_i = 0
	if m % 2:
		start_j = 1
		for i in range(start_i, n):
			if M[i][0]:
				if i == n - 1:
					M[i][0] = 0
					M[i][1] = 1 - M[i][1]
					M[i - 1][1] = 1 - M[i - 1][1]
					out.append((i, 0, i, 1, i - 1, 1))
				elif M[i + 1][0]:
					M[i][0] = 0
					M[i + 1][0] = 0
					M[i][1] = 1 - M[i][1]
					out.append((i, 0, i + 1, 0, i, 1))
				else:
					M[i][0] = 0
					M[i][1] = 1 - M[i][1]
					M[i + 1][1] = 1 - M[i + 1][1]
					out.append((i, 0, i, 1, i + 1, 1))
	else:
		start_j = 0
	for i in range(start_i, n, 2):
		for j in range(start_j, m, 2):
			(a, b, c, d) = (M[i][j], M[i][j + 1], M[i + 1][j], M[i + 1][j + 1])
			if a + b + c + d == 1:
				if a:
					out += change1(i, j)
				elif b:
					out += change1(i, j + 1)
				elif c:
					out += change1(i + 1, j)
				else:
					out += change1(i + 1, j + 1)
			elif a + b + c + d == 2:
				if a and d:
					out += change2(i, j, 0)
				elif b and c:
					out += change2(i, j, 1)
				elif a and c:
					out += change2(i, j, 2)
				elif b and d:
					out += change2(i, j, 3)
				elif a and b:
					out += change2(i, j, 4)
				else:
					out += change2(i, j, 5)
			elif a + b + c + d == 3:
				if not a:
					out += change3(i, j, 0)
				elif not b:
					out += change3(i, j, 1)
				elif not c:
					out += change3(i, j, 2)
				else:
					out += change3(i, j, 3)
			elif a + b + c + d == 4:
				out += change3(i, j, 0)
				out += change1(i, j)
	print(len(out))
	for row in out:
		for elem in row:
			print(elem + 1, end=' ')
		print()


import os
import sys
from io import BytesIO, IOBase
import heapq as h
import bisect
from types import GeneratorType
BUFSIZE = 8192

class SortedList:

	def __init__(self, iterable=[], _load=200):
		values = sorted(iterable)
		self._len = _len = len(values)
		self._load = _load
		self._lists = _lists = [values[i:i + _load] for i in range(0, _len, _load)]
		self._list_lens = [len(_list) for _list in _lists]
		self._mins = [_list[0] for _list in _lists]
		self._fen_tree = []
		self._rebuild = True

	def _fen_build(self):
		self._fen_tree[:] = self._list_lens
		_fen_tree = self._fen_tree
		for i in range(len(_fen_tree)):
			if i | i + 1 < len(_fen_tree):
				_fen_tree[i | i + 1] += _fen_tree[i]
		self._rebuild = False

	def _fen_update(self, index, value):
		if not self._rebuild:
			_fen_tree = self._fen_tree
			while index < len(_fen_tree):
				_fen_tree[index] += value
				index |= index + 1

	def _fen_query(self, end):
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		x = 0
		while end:
			x += _fen_tree[end - 1]
			end &= end - 1
		return x

	def _fen_findkth(self, k):
		_list_lens = self._list_lens
		if k < _list_lens[0]:
			return (0, k)
		if k >= self._len - _list_lens[-1]:
			return (len(_list_lens) - 1, k + _list_lens[-1] - self._len)
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		idx = -1
		for d in reversed(range(len(_fen_tree).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(_fen_tree) and k >= _fen_tree[right_idx]:
				idx = right_idx
				k -= _fen_tree[idx]
		return (idx + 1, k)

	def _delete(self, pos, idx):
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len -= 1
		self._fen_update(pos, -1)
		del _lists[pos][idx]
		_list_lens[pos] -= 1
		if _list_lens[pos]:
			_mins[pos] = _lists[pos][0]
		else:
			del _lists[pos]
			del _list_lens[pos]
			del _mins[pos]
			self._rebuild = True

	def _loc_left(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(lo, pos) = (-1, len(_lists) - 1)
		while lo + 1 < pos:
			mi = lo + pos >> 1
			if value <= _mins[mi]:
				pos = mi
			else:
				lo = mi
		if pos and value <= _lists[pos - 1][-1]:
			pos -= 1
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value <= _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def _loc_right(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(pos, hi) = (0, len(_lists))
		while pos + 1 < hi:
			mi = pos + hi >> 1
			if value < _mins[mi]:
				hi = mi
			else:
				pos = mi
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value < _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def add(self, value):
		_load = self._load
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len += 1
		if _lists:
			(pos, idx) = self._loc_right(value)
			self._fen_update(pos, 1)
			_list = _lists[pos]
			_list.insert(idx, value)
			_list_lens[pos] += 1
			_mins[pos] = _list[0]
			if _load + _load < len(_list):
				_lists.insert(pos + 1, _list[_load:])
				_list_lens.insert(pos + 1, len(_list) - _load)
				_mins.insert(pos + 1, _list[_load])
				_list_lens[pos] = _load
				del _list[_load:]
				self._rebuild = True
		else:
			_lists.append([value])
			_mins.append(value)
			_list_lens.append(1)
			self._rebuild = True

	def discard(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_right(value)
			if idx and _lists[pos][idx - 1] == value:
				self._delete(pos, idx - 1)

	def remove(self, value):
		_len = self._len
		self.discard(value)
		if _len == self._len:
			raise ValueError('{0!r} not in list'.format(value))

	def pop(self, index=-1):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		value = self._lists[pos][idx]
		self._delete(pos, idx)
		return value

	def bisect_left(self, value):
		(pos, idx) = self._loc_left(value)
		return self._fen_query(pos) + idx

	def bisect_right(self, value):
		(pos, idx) = self._loc_right(value)
		return self._fen_query(pos) + idx

	def count(self, value):
		return self.bisect_right(value) - self.bisect_left(value)

	def __len__(self):
		return self._len

	def __getitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		return self._lists[pos][idx]

	def __delitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		self._delete(pos, idx)

	def __contains__(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_left(value)
			return idx < len(_lists[pos]) and _lists[pos][idx] == value
		return False

	def __iter__(self):
		return (value for _list in self._lists for value in _list)

	def __reversed__(self):
		return (value for _list in reversed(self._lists) for value in reversed(_list))

	def __repr__(self):
		return 'SortedList({0})'.format(list(self))

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		import os
		self.os = os
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			self.os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
import collections as col
import math, string

def getInts():
	return [int(s) for s in input().split()]

def getInt():
	return int(input())

def getStrs():
	return [s for s in input().split()]

def getStr():
	return input()

def listStr():
	return list(input())
MOD = 10 ** 9 + 7
mod = 10 ** 9 + 7
t = int(input())
p = 10 ** 9 + 7

def ncr_util():
	inv[0] = inv[1] = 1
	fact[0] = fact[1] = 1
	for i in range(2, 300001):
		inv[i] = inv[i % p] * (p - p // i) % p
	for i in range(1, 300001):
		inv[i] = inv[i - 1] * inv[i] % p
		fact[i] = fact[i - 1] * i % p

def z_array(s1):
	n = len(s1)
	z = [0] * n
	(l, r, k) = (0, 0, 0)
	for i in range(1, n):
		if i > r:
			(l, r) = (i, i)
			while r < n and s1[r - l] == s1[r]:
				r += 1
			z[i] = r - l
			r -= 1
		else:
			k = i - l
			if z[k] < r - i + 1:
				z[i] = z[k]
			else:
				l = i
				while r < n and s1[r - l] == s1[r]:
					r += 1
				z[i] = r - l
				r -= 1
	return z

def solve3(ans, d, i, j):
	ans1 = []
	for i1 in range(i, i + 2):
		for j1 in range(j, j + 2):
			if d[i1][j1] == 1:
				d[i1][j1] ^= 1
				ans1.append(i1)
				ans1.append(j1)
	ans.append(ans1)

def solve2(ans, d, i, j):
	cnt = 0
	ans1 = []
	for i1 in range(i, i + 2):
		for j1 in range(j, j + 2):
			if d[i1][j1] == 0:
				ans1.append(i1)
				ans1.append(j1)
				d[i1][j1] ^= 1
			elif cnt == 0 and d[i1][j1] == 1:
				cnt = 1
				ans1.append(i1)
				ans1.append(j1)
				d[i1][j1] ^= 1
	ans.append(ans1)
	solve3(ans, d, i, j)

def solve1(ans, d, i, j):
	cnt = 0
	ans1 = []
	for i1 in range(i, i + 2):
		for j1 in range(j, j + 2):
			if d[i1][j1] == 1:
				ans1.append(i1)
				ans1.append(j1)
				d[i1][j1] ^= 1
			elif d[i1][j1] == 0 and cnt < 2:
				cnt += 1
				ans1.append(i1)
				ans1.append(j1)
				d[i1][j1] ^= 1
	ans.append(ans1)
	solve2(ans, d, i, j)

def solve4(ans, d, i, j):
	d[i][j] ^= 1
	d[i][j + 1] ^= 1
	d[i + 1][j] ^= 1
	ans.append([i, j, i, j + 1, i + 1, j])
	solve1(ans, d, i, j)

def solve_util(ans, d, i, j):
	(x1, y) = (0, 0)
	for i1 in range(i, i + 2):
		for j1 in range(j, j + 2):
			if d[i1][j1] == 1:
				x1 += 1
	if x1 == 4:
		solve4(ans, d, i, j)
	elif x1 == 3:
		solve3(ans, d, i, j)
	elif x1 == 2:
		solve2(ans, d, i, j)
	elif x1 == 1:
		solve1(ans, d, i, j)

def solve():
	ans = []
	d = {}
	for i in range(n):
		d[i] = []
		for j in range(m):
			if l[i][j] == '0':
				d[i].append(0)
			else:
				d[i].append(1)
	(i1, j1) = (0, 0)
	for i1 in range(n - 2):
		for j1 in range(m):
			if d[i1][j1] == 1:
				if j1 == m - 1:
					ans.append([i1, j1, i1 + 1, j1, i1 + 1, j1 - 1])
					d[i1][j1] ^= 1
					d[i1 + 1][j1] ^= 1
					d[i1 + 1][j1 - 1] ^= 1
				else:
					ans.append([i1, j1, i1 + 1, j1, i1, j1 + 1])
					d[i1][j1] ^= 1
					d[i1 + 1][j1] ^= 1
					d[i1][j1 + 1] ^= 1
	if m % 2 != 0:
		if d[n - 2][m - 1] == 1 and d[n - 1][m - 1] == 1:
			ans.append([n - 2, m - 1, n - 1, m - 1, n - 2, m - 2])
			d[n - 2][m - 1] ^= 1
			d[n - 1][m - 1] ^= 1
			d[n - 2][m - 2] ^= 1
		elif d[n - 2][m - 1] == 1:
			ans.append([n - 2, m - 1, n - 2, m - 2, n - 1, m - 2])
			d[n - 2][m - 1] ^= 1
			d[n - 2][m - 2] ^= 1
			d[n - 1][m - 2] ^= 1
		elif d[n - 1][m - 1] == 1:
			ans.append([n - 1, m - 1, n - 1, m - 2, n - 2, m - 2])
			d[n - 1][m - 1] ^= 1
			d[n - 1][m - 2] ^= 1
			d[n - 2][m - 2] ^= 1
	j1 = 0
	cnt1 = m // 2
	while cnt1:
		solve_util(ans, d, n - 2, j1)
		j1 += 2
		cnt1 -= 1
	print(len(ans))
	for i in range(len(ans)):
		for j in range(6):
			print(ans[i][j] + 1, end=' ')
		print()
for _ in range(t):
	(n, m) = map(int, input().split())
	l = []
	for i in range(n):
		l.append(input())
	solve()


import sys
try:
	(sys.stdin, sys.stdout) = (open('in.txt', 'r'), open('out.txt', 'w'))
except:
	pass
ii1 = lambda : int(sys.stdin.readline().strip())
is1 = lambda : sys.stdin.readline().strip()
iia = lambda : list(map(int, sys.stdin.readline().strip().split()))
isa = lambda : sys.stdin.readline().strip().split()
from collections import Counter
from math import *
from random import sample, shuffle

def fun(p, n, m):
	Res = []
	for i in range(1, n - 1):
		for j in range(1, m):
			if p[i][j] == '0' and p[i][j + 1] == '0':
				continue
			V = []
			if p[i][j] == '1':
				V.append([i, j])
			if p[i][j + 1] == '1':
				V.append([i, j + 1])
			for k in range(j, j + 2):
				if len(V) < 3:
					V.append([i + 1, k])
			Res.append(V)
			for (x, y) in V:
				if p[x][y] == '1':
					p[x][y] = '0'
				else:
					p[x][y] = '1'
	for j in range(1, m):
		if p[n][j] == '0' and p[n - 1][j] == '0':
			continue
		V = []
		if p[n][j] == '1':
			V.append([n, j])
		if p[n - 1][j] == '1':
			V.append([n - 1, j])
		for k in range(n - 1, n + 1):
			if len(V) < 3:
				V.append([k, j + 1])
		Res.append(V)
		for (x, y) in V:
			if p[x][y] == '1':
				p[x][y] = '0'
			else:
				p[x][y] = '1'
	if p[n - 1][m] == '1' and p[n][m] == '0':
		V = []
		V.append([n - 1, m])
		V.append([n, m])
		V.append([n - 1, m - 1])
		Res.append(V)
		V = []
		V.append([n - 1, m - 1])
		V.append([n - 1, m])
		V.append([n, m - 1])
		Res.append(V)
		V = []
		V.append([n - 1, m])
		V.append([n, m - 1])
		V.append([n, m])
		Res.append(V)
	elif p[n - 1][m] == '0' and p[n][m] == '1':
		V = []
		V.append([n - 1, m])
		V.append([n, m])
		V.append([n - 1, m - 1])
		Res.append(V)
		V = []
		V.append([n - 1, m - 1])
		V.append([n, m])
		V.append([n, m - 1])
		Res.append(V)
		V = []
		V.append([n, m])
		V.append([n, m - 1])
		V.append([n - 1, m])
		Res.append(V)
	elif p[n - 1][m] == '1' and p[n][m] == '1':
		V = []
		V.append([n - 1, m - 1])
		V.append([n - 1, m])
		V.append([n, m - 1])
		Res.append(V)
		V = []
		V.append([n - 1, m - 1])
		V.append([n, m - 1])
		V.append([n, m])
		Res.append(V)
	print(len(Res))
	for i in range(len(Res)):
		for (x, y) in Res[i]:
			print(x, y, end=' ')
		print()
for _ in range(ii1()):
	(n, m) = iia()
	s = [[]]
	for i in range(n):
		a = [' '] + list(is1())
		s.append(a)
	fun(s, n, m)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))

def input():
	return sys.stdin.readline().rstrip('\r\n')

def getint():
	return int(input())

def getints():
	return list(map(int, input().split()))

def getint1():
	return list(map(lambda x: int(x) - 1, input().split()))

def main():
	d = {'0': 0, '1': 1}
	cases = getint()
	for t in range(cases):
		(n, m) = getints()
		matrix = []
		for i in range(n):
			matrix.append([d[i] for i in input()])
		k = 0
		out = []
		for i in range(n - 2):
			for j in range(m):
				if matrix[i][j]:
					k += 1
					if j < m - 1:
						matrix[i][j] = 0
						matrix[i + 1][j] ^= 1
						matrix[i + 1][j + 1] ^= 1
						out.append([i, j, i + 1, j, i + 1, j + 1])
					elif j == m - 1:
						matrix[i][j] = 0
						matrix[i + 1][j] ^= 1
						matrix[i + 1][j - 1] ^= 1
						out.append([i, j, i + 1, j, i + 1, j - 1])
		for i in range(m - 1):
			(x1, x2) = (matrix[n - 2][i], matrix[n - 1][i])
			if x1 == 0 and x2 == 0:
				continue
			elif x1 == 1 and x2 == 1:
				out.append([n - 2, i, n - 1, i, n - 1, i + 1])
				matrix[n - 2][i] ^= 1
				matrix[n - 1][i] ^= 1
				matrix[n - 1][i + 1] ^= 1
			elif x1 == 0 and x2 == 1:
				out.append([n - 2, i + 1, n - 1, i, n - 1, i + 1])
				matrix[n - 2][i + 1] ^= 1
				matrix[n - 1][i] ^= 1
				matrix[n - 1][i + 1] ^= 1
			elif x1 == 1 and x2 == 0:
				out.append([n - 2, i, n - 2, i + 1, n - 1, i + 1])
				matrix[n - 2][i] ^= 1
				matrix[n - 2][i + 1] ^= 1
				matrix[n - 1][i + 1] ^= 1
			k += 1
		if matrix[-1][-1] or matrix[-2][-1]:
			(x1, x2, x3, x4) = (matrix[n - 2][m - 2], matrix[n - 2][m - 1], matrix[n - 1][m - 2], matrix[n - 1][m - 1])
			if x2 == 1 and x4 == 1:
				out.append([n - 2, m - 2, n - 2, m - 1, n - 1, m - 2])
				out.append([n - 2, m - 2, n - 1, m - 2, n - 1, m - 1])
				(matrix[n - 2][m - 1], matrix[n - 1][m - 1]) = (0, 0)
				k += 2
			elif x2 == 0 and x4 == 1:
				out.append([n - 2, m - 2, n - 1, m - 2, n - 1, m - 1])
				out.append([n - 2, m - 2, n - 2, m - 1, n - 1, m - 1])
				out.append([n - 2, m - 1, n - 1, m - 2, n - 1, m - 1])
				matrix[n - 1][m - 1] = 0
				k += 3
			elif x2 == 1 and x4 == 0:
				out.append([n - 2, m - 2, n - 2, m - 1, n - 1, m - 2])
				out.append([n - 2, m - 2, n - 2, m - 1, n - 1, m - 1])
				out.append([n - 2, m - 1, n - 1, m - 2, n - 1, m - 1])
				matrix[n - 2][m - 1] = 0
				k += 3
		print(k)
		for (x1, y1, x2, y2, x3, y3) in out:
			print(x1 + 1, y1 + 1, x2 + 1, y2 + 1, x3 + 1, y3 + 1)
main()


from collections import defaultdict, deque
from heapq import heappush, heappop
from bisect import bisect_left, bisect_right
import sys, itertools, math
sys.setrecursionlimit(10 ** 5)
input = sys.stdin.readline
sqrt = math.sqrt

def LI():
	return list(map(int, input().split()))

def LF():
	return list(map(float, input().split()))

def LI_():
	return list(map(lambda x: int(x) - 1, input().split()))

def II():
	return int(input())

def IF():
	return float(input())

def S():
	return input().rstrip()

def LS():
	return S().split()

def IR(n):
	res = [None] * n
	for i in range(n):
		res[i] = II()
	return res

def LIR(n):
	res = [None] * n
	for i in range(n):
		res[i] = LI()
	return res

def FR(n):
	res = [None] * n
	for i in range(n):
		res[i] = IF()
	return res

def LIR(n):
	res = [None] * n
	for i in range(n):
		res[i] = IF()
	return res

def LIR_(n):
	res = [None] * n
	for i in range(n):
		res[i] = LI_()
	return res

def SR(n):
	res = [None] * n
	for i in range(n):
		res[i] = S()
	return res

def LSR(n):
	res = [None] * n
	for i in range(n):
		res[i] = LS()
	return res
mod = 1000000007
inf = float('INF')

def solve():
	t = II()
	kuso = {'1': '0', '0': '1'}
	f = {1: 3, 2: 2, 3: 1, 4: 4}

	def fff(g, a):
		one = a.count('1')
		if one == 0:
			return
		tmp = []
		if one == 1 or one == 3:
			for i in range(4):
				if a[i] == '1':
					tmp.append(i)
			for i in range(4):
				if len(tmp) == 3:
					break
				if a[i] == '0':
					tmp.append(i)
			for i in range(3):
				a[tmp[i]] = kuso[a[tmp[i]]]
				tmp[i] = ' '.join(map(str, g[tmp[i]]))
			ans.append(' '.join(tmp))
			fff(g, a)
			return
		else:
			for i in range(4):
				if a[i] == '0':
					tmp.append(i)
			for i in range(4):
				if len(tmp) == 3:
					break
				if a[i] == '1':
					tmp.append(i)
			for i in range(3):
				a[tmp[i]] = kuso[a[tmp[i]]]
				tmp[i] = ' '.join(map(str, g[tmp[i]]))
			ans.append(' '.join(tmp))
			fff(g, a)
			return
	for i in range(t):
		(n, m) = LI()
		s = [list(input().rstrip()) for i in range(n)]
		ans = []
		if s[-1][-1] == s[-1][-2] == s[-2][-1] == '1':
			s[-1][-1] = '0'
			s[-1][-2] = '0'
			s[-2][-1] = '0'
			tmp = []
			tmp.append(n)
			tmp.append(m)
			tmp.append(n - 1)
			tmp.append(m)
			tmp.append(n)
			tmp.append(m - 1)
			ans.append(' '.join(map(str, tmp)))
		if m & 1:
			for y in range(n - 1):
				tmp = []
				if s[y][-1] == '1':
					tmp.append(y + 1)
					tmp.append(m)
					s[y][-1] = '0'
				if s[y + 1][-1] == '1':
					tmp.append(y + 2)
					tmp.append(m)
					s[y + 1][-1] = '0'
				if tmp:
					tmp.append(y + 1)
					tmp.append(m - 1)
					s[y][m - 2] = kuso[s[y][m - 2]]
					if len(tmp) == 4:
						tmp.append(y + 2)
						tmp.append(m - 1)
						s[y + 1][m - 2] = kuso[s[y + 1][m - 2]]
					ans.append(' '.join(map(str, tmp)))
		if n & 1:
			for x in range(m - 1):
				tmp = []
				if s[-1][x] == '1':
					tmp.append(n)
					tmp.append(x + 1)
					s[-1][x] = '0'
				if s[-1][x + 1] == '1':
					tmp.append(n)
					tmp.append(x + 2)
					s[-1][x + 1] = '0'
				if tmp:
					tmp.append(n - 1)
					tmp.append(x + 1)
					s[-2][x] = kuso[s[-2][x]]
					if len(tmp) == 4:
						tmp.append(n - 1)
						tmp.append(x + 2)
						s[-2][x + 1] = kuso[s[-2][x + 1]]
					ans.append(' '.join(map(str, tmp)))
		for y in range(0, n - 1, 2):
			for x in range(0, m - 1, 2):
				a0 = s[y][x]
				a1 = s[y][x + 1]
				a2 = s[y + 1][x]
				a3 = s[y + 1][x + 1]
				s[y][x] = '0'
				s[y + 1][x] = '0'
				s[y][x + 1] = '0'
				s[y + 1][x + 1] = '0'
				g = [[y + 1, x + 1], [y + 1, x + 2], [y + 2, x + 1], [y + 2, x + 2]]
				a = [a0, a1, a2, a3]
				c = a.count('1')
				if c == 0:
					continue
				fff(g, a)
		print(len(ans))
		for i in ans:
			print(i)
	return
solve()


import os
import sys
from io import BytesIO, IOBase
_str = str
BUFSIZE = 8192

def str(x=b''):
	return x if type(x) is bytes else _str(x).encode()

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def inp():
	return sys.stdin.readline().rstrip()

def mpint():
	return map(int, inp().split(' '))

def itg():
	return int(inp())

class State:

	def __init__(self, state, operations):
		self.states_num = {state: 0}
		self.states = [state]
		self._path = {}
		self.DIAMETER = 0
		new_sts = [0]
		while new_sts:
			self.DIAMETER += 1
			(cur_sts, new_sts) = (new_sts, [])
			for i in cur_sts:
				for (op, f) in enumerate(operations):
					state = f(self.states[i])
					if state not in self.states_num:
						j = self.states_num[state] = len(self.states)
						self.states.append(state)
						new_sts.append(j)
					else:
						j = self.states_num[state]
					self._path[i, j] = (i, op)
		self.SIZE = n = len(self.states_num)
		self.distance = dis = [[0 if i == j else 10 ** 6 for i in range(n)] for j in range(n)]
		for (i, j) in self._path.keys():
			self.distance[i][j] = 1
		for k in range(n):
			for i in range(n):
				for j in range(n):
					if dis[i][k] + dis[k][j] < dis[i][j]:
						dis[i][j] = dis[i][k] + dis[k][j]
						self._path[i, j] = self._path[k, j]

	def path(self, st1, st2):
		u = self.states_num[st1]
		v = self.states_num[st2]
		result = []
		while u != v:
			(v, op) = self._path[u, v]
			result.append(op)
		return result[::-1]

	def min_path(self, st1, states):
		result = [-1] * self.DIAMETER
		choice = -1
		for (i, st2) in enumerate(states):
			path = self.path(st1, st2)
			if len(path) < len(result):
				result = path
				choice = i
		return (result, choice)

def op0(st):
	return (st[0], st[1] ^ 1, st[2] ^ 1, st[3] ^ 1)

def op1(st):
	return (st[0] ^ 1, st[1], st[2] ^ 1, st[3] ^ 1)

def op2(st):
	return (st[0] ^ 1, st[1] ^ 1, st[2], st[3] ^ 1)

def op3(st):
	return (st[0] ^ 1, st[1] ^ 1, st[2] ^ 1, st[3])
zero = (0, 0, 0, 0)
ST = State(zero, (op0, op1, op2, op3))
right_zero = (zero, (0, 0, 1, 0), (1, 0, 0, 0), (1, 0, 1, 0))
bottom_zero = (zero, (0, 1, 0, 0), (1, 0, 0, 0), (1, 1, 0, 0))

def solve():
	(n, m) = mpint()
	matrix = [list(map(int, inp())) for _ in range(n)]
	output = []
	if m & 1:
		for i in range(n - 1):
			(y, x) = (i, m - 2)
			st = (matrix[y][x], matrix[y][x + 1], matrix[y + 1][x], matrix[y + 1][x + 1])
			(path, choice) = ST.min_path(st, right_zero)
			(matrix[y][x], matrix[y][x + 1], matrix[y + 1][x], matrix[y + 1][x + 1]) = right_zero[choice]
			y += 1
			x += 1
			for op in path:
				pos = [y, x, y, x + 1, y + 1, x, y + 1, x + 1]
				del pos[op << 1], pos[op << 1]
				output.append(pos)
	if n & 1:
		for j in range(m - 1 - (m & 1)):
			(y, x) = (n - 2, j)
			st = (matrix[y][x], matrix[y][x + 1], matrix[y + 1][x], matrix[y + 1][x + 1])
			(path, choice) = ST.min_path(st, bottom_zero)
			(matrix[y][x], matrix[y][x + 1], matrix[y + 1][x], matrix[y + 1][x + 1]) = bottom_zero[choice]
			y += 1
			x += 1
			for op in path:
				pos = [y, x, y, x + 1, y + 1, x, y + 1, x + 1]
				del pos[op << 1], pos[op << 1]
				output.append(pos)
	for i in range(n >> 1):
		for j in range(m >> 1):
			(y, x) = (i << 1, j << 1)
			st = (matrix[y][x], matrix[y][x + 1], matrix[y + 1][x], matrix[y + 1][x + 1])
			pos = [y, x, y, x + 1, y + 1, x, y + 1, x + 1]
			for k in range(4):
				matrix[pos[k * 2]][pos[k * 2 + 1]] = 0
			y += 1
			x += 1
			for op in ST.path(st, zero):
				pos = [y, x, y, x + 1, y + 1, x, y + 1, x + 1]
				del pos[op << 1], pos[op << 1]
				output.append(pos)
	assert len(output) <= n * m
	print(len(output))
	for out in output:
		print(*out)

def main():
	for _ in range(itg()):
		solve()
DEBUG = 0
URL = ''
if DEBUG == 1:
	import requests
	from ACgenerator.Y_Test_Case_Runner import TestCaseRunner
	runner = TestCaseRunner(main, URL)
	inp = runner.input_stream
	print = runner.output_stream
	runner.checking()
elif DEBUG == 2:
	main()
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
	main()


def printans(ans):
	print(len(ans))
	for i in ans:
		for (x, y) in i:
			print(x + 1, y + 1, end=' ')
		print()

def update(arr, lis):
	for (i, j) in lis:
		arr[i][j] = 1 - arr[i][j]

def considersquare(i, j, arr, ans, lastcol, last):
	a = arr[i][j]
	b = arr[i + 1][j]
	c = arr[i][j + 1]
	d = arr[i + 1][j + 1]
	if last and lastcol:
		while True:
			a = arr[i][j]
			b = arr[i + 1][j]
			c = arr[i][j + 1]
			d = arr[i + 1][j + 1]
			if a + b + c + d == 0:
				return
			elif a + b + c + d == 1:
				if a == 1 or b == 1 or d == 1:
					ans.append([(i, j), (i + 1, j), (i + 1, j + 1)])
					update(arr, [(i, j), (i + 1, j), (i + 1, j + 1)])
				elif c == 1:
					ans.append([(i, j), (i, j + 1), (i + 1, j + 1)])
					update(arr, [(i, j), (i, j + 1), (i + 1, j + 1)])
			elif a + b + c + d == 2:
				lis = []
				for p in (i, i + 1):
					for q in (j, j + 1):
						if arr[p][q] == 0:
							lis.append((p, q))
				for p in (i, i + 1):
					for q in (j, j + 1):
						if arr[p][q] == 1 and len(lis) < 3:
							lis.append((p, q))
				ans.append(lis)
				update(arr, lis)
			elif a + b + c + d == 3:
				lis = []
				for p in (i, i + 1):
					for q in (j, j + 1):
						if arr[p][q] == 1:
							lis.append((p, q))
				ans.append(lis)
				update(arr, lis)
			elif a + b + c + d == 4:
				ans.append([(i, j), (i + 1, j), (i + 1, j + 1)])
				update(arr, [(i, j), (i + 1, j), (i + 1, j + 1)])
	elif lastcol:
		if a == 0 and c == 0:
			return
		elif a == 1 and c == 0:
			ans.append([(i, j), (i + 1, j), (i + 1, j + 1)])
			update(arr, [(i, j), (i + 1, j), (i + 1, j + 1)])
		elif c == 1 and a == 0:
			ans.append([(i + 1, j), (i, j + 1), (i + 1, j + 1)])
			update(arr, [(i + 1, j), (i, j + 1), (i + 1, j + 1)])
		elif a == 1 and c == 1:
			ans.append([(i, j), (i, j + 1), (i + 1, j + 1)])
			update(arr, [(i, j), (i, j + 1), (i + 1, j + 1)])
	elif a == 0 and b == 0:
		return
	elif a == 1 and b == 0:
		ans.append([(i, j), (i, j + 1), (i + 1, j + 1)])
		update(arr, [(i, j), (i, j + 1), (i + 1, j + 1)])
	elif b == 1 and a == 0:
		ans.append([(i + 1, j), (i, j + 1), (i + 1, j + 1)])
		update(arr, [(i + 1, j), (i, j + 1), (i + 1, j + 1)])
	elif a == 1 and b == 1:
		ans.append([(i, j), (i + 1, j), (i + 1, j + 1)])
		update(arr, [(i, j), (i + 1, j), (i + 1, j + 1)])
for _ in range(int(input())):
	(n, m) = [int(c) for c in input().split()]
	arr = []
	for i in range(n):
		ar = [int(c) for c in input()]
		arr.append(ar)
	ans = []
	count = 0
	for i in range(n - 1):
		for j in range(m - 1):
			considersquare(i, j, arr, ans, j == m - 2, i == n - 2)
	if len(ans) == n * m + 1:
		raise ValueError()
	printans(ans)


import math

def main():
	(n, m) = map(int, input().split())
	table = []
	for i in range(n):
		line = input()
		table.append(list(line))
	moves = ''
	moves_n = 0
	for i in range(0, n - 2):
		for k in range(0, m - 1, 2):
			swap_down = 0
			if table[i][k] == '1':
				table[i][k] = '0'
				moves += str(i + 1) + ' ' + str(k + 1) + ' '
				swap_down += 1
			if table[i][k + 1] == '1':
				table[i][k + 1] = '0'
				moves += str(i + 1) + ' ' + str(k + 2) + ' '
				swap_down += 1
			if swap_down > 0:
				moves += str(i + 2) + ' ' + str(k + 1) + ' '
				if table[i + 1][k] == '1':
					table[i + 1][k] = '0'
				else:
					table[i + 1][k] = '1'
				if swap_down == 1:
					moves += str(i + 2) + ' ' + str(k + 2) + ' '
					if table[i + 1][k + 1] == '1':
						table[i + 1][k + 1] = '0'
					else:
						table[i + 1][k + 1] = '1'
				moves += '\n'
				moves_n += 1
		if m % 2 != 0:
			if table[i][m - 1] == '1':
				table[i][m - 1] = '0'
				moves += str(i + 1) + ' ' + str(m) + ' '
				moves += str(i + 2) + ' ' + str(m - 1) + ' '
				moves += str(i + 2) + ' ' + str(m) + ' '
				if table[i + 1][m - 1] == '0':
					table[i + 1][m - 1] = '1'
				else:
					table[i + 1][m - 1] = '0'
				if table[i + 1][m - 2] == '0':
					table[i + 1][m - 2] = '1'
				else:
					table[i + 1][m - 2] = '0'
				moves += '\n'
				moves_n += 1
	for i in range(0, m - 2):
		swap_right = 0
		if table[n - 1][i] == '1':
			table[n - 1][i] = '0'
			moves += str(n) + ' ' + str(i + 1) + ' '
			swap_right += 1
		if table[n - 2][i] == '1':
			table[n - 2][i] = '0'
			moves += str(n - 1) + ' ' + str(i + 1) + ' '
			swap_right += 1
		if swap_right > 0:
			moves += str(n) + ' ' + str(i + 2) + ' '
			if table[n - 1][i + 1] == '1':
				table[n - 1][i + 1] = '0'
			else:
				table[n - 1][i + 1] = '1'
			if swap_right == 1:
				moves += str(n - 1) + ' ' + str(i + 2) + ' '
				if table[n - 2][i + 1] == '1':
					table[n - 2][i + 1] = '0'
				else:
					table[n - 2][i + 1] = '1'
			moves += '\n'
			moves_n += 1
	last_sqr = [[table[-2][-2], table[-2][-1]], [table[-1][-2], table[-1][-1]]]
	ones = []
	zeros = []
	for i in range(2):
		for k in range(2):
			if last_sqr[i][k] == '1':
				ones.append([i, k])
			else:
				zeros.append([i, k])
	if len(ones) == 4:
		moves += str(n - 1 + ones[0][0]) + ' ' + str(m - 1 + ones[0][1]) + ' '
		moves += str(n - 1 + ones[1][0]) + ' ' + str(m - 1 + ones[1][1]) + ' '
		moves += str(n - 1 + ones[2][0]) + ' ' + str(m - 1 + ones[2][1]) + ' '
		moves += '\n'
		moves_n += 1
		last_sqr[ones[0][0]][ones[0][1]] = '0'
		last_sqr[ones[1][0]][ones[1][1]] = '0'
		last_sqr[ones[2][0]][ones[2][1]] = '0'
	ones = []
	zeros = []
	for i in range(2):
		for k in range(2):
			if last_sqr[i][k] == '1':
				ones.append([i, k])
			else:
				zeros.append([i, k])
	if len(ones) == 1:
		moves += str(n - 1 + ones[0][0]) + ' ' + str(m - 1 + ones[0][1]) + ' '
		moves += str(n - 1 + zeros[0][0]) + ' ' + str(m - 1 + zeros[0][1]) + ' '
		moves += str(n - 1 + zeros[1][0]) + ' ' + str(m - 1 + zeros[1][1]) + ' '
		last_sqr[ones[0][0]][ones[0][1]] = '0'
		last_sqr[zeros[0][0]][zeros[0][1]] = '1'
		last_sqr[zeros[1][0]][zeros[1][1]] = '1'
		moves += '\n'
		moves_n += 1
	ones = []
	zeros = []
	for i in range(2):
		for k in range(2):
			if last_sqr[i][k] == '1':
				ones.append([i, k])
			else:
				zeros.append([i, k])
	if len(ones) == 2:
		moves += str(n - 1 + ones[0][0]) + ' ' + str(m - 1 + ones[0][1]) + ' '
		moves += str(n - 1 + zeros[0][0]) + ' ' + str(m - 1 + zeros[0][1]) + ' '
		moves += str(n - 1 + zeros[1][0]) + ' ' + str(m - 1 + zeros[1][1]) + ' '
		last_sqr[ones[0][0]][ones[0][1]] = '0'
		last_sqr[zeros[0][0]][zeros[0][1]] = '1'
		last_sqr[zeros[1][0]][zeros[1][1]] = '1'
		moves += '\n'
		moves_n += 1
	ones = []
	zeros = []
	for i in range(2):
		for k in range(2):
			if last_sqr[i][k] == '1':
				ones.append([i, k])
			else:
				zeros.append([i, k])
	if len(ones) == 3:
		moves += str(n - 1 + ones[0][0]) + ' ' + str(m - 1 + ones[0][1]) + ' '
		moves += str(n - 1 + ones[1][0]) + ' ' + str(m - 1 + ones[1][1]) + ' '
		moves += str(n - 1 + ones[2][0]) + ' ' + str(m - 1 + ones[2][1]) + ' '
		moves += '\n'
		moves_n += 1
		last_sqr[ones[0][0]][ones[0][1]] = '0'
		last_sqr[ones[1][0]][ones[1][1]] = '0'
		last_sqr[ones[2][0]][ones[2][1]] = '0'
	print(moves_n)
	print(moves, end='')
t = int(input())
for i in range(t):
	main()


t = int(input())
for i in range(t):
	(n, m) = map(int, input().split())
	if n == 3 and m == 3:
		A = [[0] * (n + 1)] + [[0] + list(map(int, list(input()))) for _ in range(m)]
		ans = []
		for i in range(1, m - 1):
			for j in range(1, n + 1):
				if A[i][j]:
					ans.append([i, j, i + 1, j, i + 1, j + 1 if j < n else j - 1])
					A[i][j] ^= 1
					A[i + 1][j] ^= 1
					A[i + 1][j + 1 if j < n else j - 1] ^= 1
		for j in range(1, n - 1):
			if A[m - 1][j] and A[m][j]:
				ans.append([m - 1, j, m, j, m - 1, j + 1])
				A[m - 1][j] ^= 1
				A[m][j] ^= 1
				A[m - 1][j + 1] ^= 1
			elif A[m - 1][j]:
				ans.append([m - 1, j, m - 1, j + 1, m, j + 1])
				A[m - 1][j] ^= 1
				A[m - 1][j + 1] ^= 1
				A[m][j + 1] ^= 1
			elif A[m][j]:
				ans.append([m, j, m, j + 1, m - 1, j + 1])
				A[m][j] ^= 1
				A[m][j + 1] ^= 1
				A[m - 1][j + 1] ^= 1
		if A[m - 1][n - 1] ^ A[m - 1][n] ^ A[m][n - 1]:
			ans.append([m - 1, n - 1, m - 1, n, m, n - 1])
		if A[m - 1][n - 1] ^ A[m][n - 1] ^ A[m][n]:
			ans.append([m - 1, n - 1, m, n - 1, m, n])
		if A[m][n - 1] ^ A[m][n] ^ A[m - 1][n]:
			ans.append([m, n - 1, m, n, m - 1, n])
		if A[m][n] ^ A[m - 1][n] ^ A[m - 1][n - 1]:
			ans.append([m, n, m - 1, n, m - 1, n - 1])
		print(len(ans))
		for a in ans:
			print(*a)
	else:
		b = []
		for j in range(n):
			s = input()
			c = []
			for j in s:
				c.append(int(j))
			b.append(c)
		res = []
		i = 0
		while i < n:
			j = 0
			while j < m:
				if i < n - 1 and j < m - 1:
					pass
				elif i < n - 1 and j == m - 1:
					if b[i][m - 2] == 1 and b[i + 1][m - 2] == 1:
						if b[i][m - 1] == 1 and b[i + 1][m - 1] == 0:
							res.append([[i, m - 2], [i + 1, m - 2], [i, m - 1]])
							b[i][m - 1] = 0
							b[i][m - 2] = 0
							b[i + 1][m - 1] = 0
							b[i + 1][m - 2] = 0
						elif b[i][m - 1] == 0 and b[i + 1][m - 1] == 1:
							res.append([[i, m - 2], [i + 1, m - 2], [i + 1, m - 1]])
							b[i][m - 1] = 0
							b[i][m - 2] = 0
							b[i + 1][m - 1] = 0
							b[i + 1][m - 2] = 0
				elif i == n - 1 and j < m - 1:
					if b[n - 2][j] == 1 and b[n - 2][j + 1] == 1:
						if b[n - 1][j] == 1 and b[n - 1][j + 1] == 0:
							res.append([[n - 2, j], [n - 2, j + 1], [n - 1, j]])
							b[n - 1][j] = 0
							b[n - 1][j + 1] = 0
							b[n - 2][j] = 0
							b[n - 2][j + 1] = 0
						elif b[n - 1][j] == 0 and b[n - 1][j + 1] == 1:
							res.append([[n - 2, j], [n - 2, j + 1], [n - 1, j + 1]])
							b[n - 1][j] = 0
							b[n - 1][j + 1] = 0
							b[n - 2][j] = 0
							b[n - 2][j + 1] = 0
				j += 2
			i += 2
		i = 0
		while i < n:
			j = 0
			while j < m:
				if i < n - 1 and j < m - 1:
					ones = []
					zero = []
					on = 0
					z = 0
					for w in range(2):
						for e in range(2):
							if b[i + w][j + e] == 1:
								ones.append([i + w, j + e])
								on += 1
							else:
								zero.append([i + w, j + e])
								z += 1
							b[i + w][j + e] = 0
					if on == 4:
						f = ones[0]
						se = ones[1]
						th = ones[2]
						frth = ones[3]
						res.append([f, se, th])
						res.append([f, th, frth])
						res.append([f, se, frth])
						res.append([se, th, frth])
					elif on == 3:
						f = ones[0]
						se = ones[1]
						th = ones[2]
						frth = zero[0]
						res.append([f, se, th])
					elif on == 2:
						f = ones[0]
						th = ones[1]
						se = zero[0]
						frth = zero[1]
						res.append([f, se, frth])
						res.append([se, th, frth])
					elif on == 1:
						f = zero[0]
						se = zero[1]
						th = zero[2]
						frth = ones[0]
						res.append([f, th, frth])
						res.append([f, se, frth])
						res.append([se, th, frth])
				elif i < n - 1 and j == m - 1:
					ones = []
					zero = []
					on = 0
					z = 0
					for w in range(2):
						for e in range(2):
							if b[i + w][j + e - 1] == 1:
								ones.append([i + w, j + e - 1])
								on += 1
							else:
								zero.append([i + w, j + e - 1])
								z += 1
							b[i + w][j + e - 1] = 0
					if on == 4:
						f = ones[0]
						se = ones[1]
						th = ones[2]
						frth = ones[3]
						res.append([f, se, th])
						res.append([f, th, frth])
						res.append([f, se, frth])
						res.append([se, th, frth])
					elif on == 3:
						f = ones[0]
						se = ones[1]
						th = ones[2]
						frth = zero[0]
						res.append([f, se, th])
					elif on == 2:
						f = ones[0]
						th = ones[1]
						se = zero[0]
						frth = zero[1]
						res.append([f, se, frth])
						res.append([se, th, frth])
					elif on == 1:
						f = zero[0]
						se = zero[1]
						th = zero[2]
						frth = ones[0]
						res.append([f, th, frth])
						res.append([f, se, frth])
						res.append([se, th, frth])
				elif i == n - 1 and j < m - 1:
					ones = []
					zero = []
					on = 0
					z = 0
					for w in range(2):
						for e in range(2):
							if b[i + w - 1][j + e] == 1:
								ones.append([i + w - 1, j + e])
								on += 1
							else:
								zero.append([i + w - 1, j + e])
								z += 1
							b[i + w - 1][j + e] = 0
					if on == 4:
						f = ones[0]
						se = ones[1]
						th = ones[2]
						frth = ones[3]
						res.append([f, se, th])
						res.append([f, th, frth])
						res.append([f, se, frth])
						res.append([se, th, frth])
					elif on == 3:
						f = ones[0]
						se = ones[1]
						th = ones[2]
						frth = zero[0]
						res.append([f, se, th])
					elif on == 2:
						f = ones[0]
						th = ones[1]
						se = zero[0]
						frth = zero[1]
						res.append([f, se, frth])
						res.append([se, th, frth])
					elif on == 1:
						f = zero[0]
						se = zero[1]
						th = zero[2]
						frth = ones[0]
						res.append([f, th, frth])
						res.append([f, se, frth])
						res.append([se, th, frth])
				else:
					ones = []
					zero = []
					on = 0
					z = 0
					for w in range(2):
						for e in range(2):
							if b[i + w - 1][j + e - 1] == 1:
								ones.append([i + w - 1, j + e - 1])
								on += 1
							else:
								zero.append([i + w - 1, j + e - 1])
								z += 1
							b[i + w - 1][j + e - 1] = 0
					if on == 4:
						f = ones[0]
						se = ones[1]
						th = ones[2]
						frth = ones[3]
						res.append([f, se, th])
						res.append([f, th, frth])
						res.append([f, se, frth])
						res.append([se, th, frth])
					elif on == 3:
						f = ones[0]
						se = ones[1]
						th = ones[2]
						frth = zero[0]
						res.append([f, se, th])
					elif on == 2:
						f = ones[0]
						th = ones[1]
						se = zero[0]
						frth = zero[1]
						res.append([f, se, frth])
						res.append([se, th, frth])
					elif on == 1:
						f = zero[0]
						se = zero[1]
						th = zero[2]
						frth = ones[0]
						res.append([f, th, frth])
						res.append([f, se, frth])
						res.append([se, th, frth])
				j += 2
			i += 2
		print(len(res))
		for j in res:
			s = []
			for k in j:
				s.append(k[0] + 1)
				s.append(k[1] + 1)
			print(*s)


import os
import sys
from io import BytesIO, IOBase

def main():
	for t in range(int(input())):
		(n, m) = map(int, input().split())
		a = []
		for i in range(n):
			a.append(list(input()))
		ops = []

		def f(b, c, e, f2, g, h):
			ops.append((b + 1, c + 1, e + 1, f2 + 1, g + 1, h + 1))
			a[b][c] = '1' if a[b][c] == '0' else '0'
			a[e][f2] = '1' if a[e][f2] == '0' else '0'
			a[g][h] = '1' if a[g][h] == '0' else '0'
		if m % 2 == 1:
			for i in range(n - 1):
				if a[i][0] == '1':
					f(i, 0, i, 1, i + 1, 1)
			if a[n - 1][0] == '1':
				f(n - 1, 0, n - 1, 1, n - 2, 1)
		for j in range(m % 2, m, 2):
			for i in range(n - 2):
				if a[i][j] == '1':
					f(i, j, i + 1, j, i + 1, j + 1)
				if a[i][j + 1] == '1':
					f(i, j + 1, i + 1, j, i + 1, j + 1)
			q = ''.join([a[n - 2][j], a[n - 2][j + 1], a[n - 1][j], a[n - 1][j + 1]])
			if q == '1111':
				f(n - 2, j, n - 2, j + 1, n - 1, j)
				f(n - 2, j, n - 2, j + 1, n - 1, j + 1)
				f(n - 2, j, n - 1, j, n - 1, j + 1)
				f(n - 2, j + 1, n - 1, j, n - 1, j + 1)
			elif q == '1110':
				f(n - 2, j, n - 2, j + 1, n - 1, j)
			elif q == '1011':
				f(n - 2, j, n - 1, j, n - 1, j + 1)
			elif q == '1101':
				f(n - 2, j, n - 2, j + 1, n - 1, j + 1)
			elif q == '0111':
				f(n - 2, j + 1, n - 1, j, n - 1, j + 1)
			elif q == '1010':
				f(n - 2, j, n - 2, j + 1, n - 1, j + 1)
				f(n - 2, j + 1, n - 1, j, n - 1, j + 1)
			elif q == '1001':
				f(n - 2, j, n - 2, j + 1, n - 1, j)
				f(n - 2, j + 1, n - 1, j, n - 1, j + 1)
			elif q == '1100':
				f(n - 2, j, n - 1, j, n - 1, j + 1)
				f(n - 2, j + 1, n - 1, j, n - 1, j + 1)
			elif q == '0101':
				f(n - 2, j, n - 2, j + 1, n - 1, j)
				f(n - 2, j, n - 1, j, n - 1, j + 1)
			elif q == '0110':
				f(n - 2, j, n - 2, j + 1, n - 1, j + 1)
				f(n - 2, j, n - 1, j, n - 1, j + 1)
			elif q == '0011':
				f(n - 2, j, n - 2, j + 1, n - 1, j)
				f(n - 2, j, n - 2, j + 1, n - 1, j + 1)
			elif q == '1000':
				f(n - 2, j, n - 2, j + 1, n - 1, j)
				f(n - 2, j, n - 2, j + 1, n - 1, j + 1)
				f(n - 2, j, n - 1, j, n - 1, j + 1)
			elif q == '0100':
				f(n - 2, j, n - 2, j + 1, n - 1, j)
				f(n - 2, j, n - 2, j + 1, n - 1, j + 1)
				f(n - 2, j + 1, n - 1, j, n - 1, j + 1)
			elif q == '0010':
				f(n - 2, j, n - 2, j + 1, n - 1, j)
				f(n - 2, j, n - 1, j, n - 1, j + 1)
				f(n - 2, j + 1, n - 1, j, n - 1, j + 1)
			elif q == '0001':
				f(n - 2, j, n - 2, j + 1, n - 1, j + 1)
				f(n - 2, j, n - 1, j, n - 1, j + 1)
				f(n - 2, j + 1, n - 1, j, n - 1, j + 1)
		print(len(ops))
		for op in ops:
			print(op[0], op[1], op[4], op[5], op[2], op[3])
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


for _ in range(int(input())):
	(n, m) = map(int, input().split())
	a = []
	for i in range(n):
		a.append(list(map(int, input().rstrip())))
	b = []
	for i in range(n - 1):
		for j in range(m):
			if j != m - 1:
				if a[i][j] == 1:
					b.extend([[i, j], [i + 1, j], [i + 1, j + 1]])
					a[i][j] = int(not a[i][j])
					a[i + 1][j] = int(not a[i + 1][j])
					a[i + 1][j + 1] = int(not a[i + 1][j + 1])
			elif a[i][j] == 1:
				b.extend([[i, j], [i + 1, j], [i + 1, j - 1]])
				a[i][j] = int(not a[i][j])
				a[i + 1][j] = int(not a[i + 1][j])
				a[i + 1][j - 1] = int(not a[i + 1][j - 1])
	i = n - 1
	x = 0
	for j in range(m - 2):
		if a[i][j] == 1 or a[i - 1][j] == 1:
			if a[i][j] == 1 and a[i - 1][j] == 1:
				b.extend([[i, j], [i - 1, j]])
				a[i][j] = int(not a[i][j])
				a[i - 1][j] = int(not a[i - 1][j])
			elif a[i][j] == 1:
				b.extend([[i, j], [i - 1, j + 1]])
				a[i][j] = int(not a[i][j])
				a[i - 1][j + 1] = int(not a[i - 1][j + 1])
			else:
				b.extend([[i - 1, j], [i - 1, j + 1]])
				a[i - 1][j] = int(not a[i - 1][j])
				a[i - 1][j + 1] = int(not a[i - 1][j + 1])
			b.append([i, j + 1])
			a[i][j + 1] = int(not a[i][j + 1])
			x += 1
	z = (a[-1][-1] == 0) + (a[-1][-2] == 0) + (a[-2][-1] == 0) + (a[-2][-2] == 0)
	f = 0
	if z == 3 and len(b) // 3 == n * m - 2:
		f = 1
		b[-3 * (x + 2)] = [-1, -1]
		a[-2][-2] = int(not a[-2][-2])
		a[-1][-2] = int(not a[-1][-2])
		a[-1][-1] = int(not a[-1][-1])
	z = (a[-1][-1] == 0) + (a[-1][-2] == 0) + (a[-2][-1] == 0) + (a[-2][-2] == 0)
	if z == 1:
		b.extend([[n - 1, m - 1], [n - 1, m - 2], [n - 2, m - 2]])
	elif z == 2 or z == 3:
		if z == 3:
			a[n - 1][m - 2] = int(not a[n - 1][m - 2])
			a[n - 1][m - 1] = int(not a[n - 1][m - 1])
			a[n - 2][m - 2] = int(not a[n - 2][m - 2])
			b.extend([[n - 2, m - 2], [n - 1, m - 2], [n - 1, m - 1]])
		if a[-2][-2] == 0:
			b.extend([[n - 2, m - 2], [n - 2, m - 1], [n - 1, m - 2], [n - 1, m - 1], [n - 2, m - 2], [n - 2, m - 1]])
		elif a[-1][-2] == 0:
			b.extend([[n - 2, m - 2], [n - 1, m - 2], [n - 2, m - 1], [n - 1, m - 1], [n - 1, m - 2], [n - 2, m - 1]])
		elif a[-1][-1] == 0:
			b.extend([[n - 2, m - 1], [n - 1, m - 1], [n - 2, m - 2], [n - 1, m - 1], [n - 2, m - 1], [n - 1, m - 2]])
	print(len(b) // 3 - f)
	for i in range(0, len(b), 3):
		if b[i][0] != -1:
			print(b[i][0] + 1, b[i][1] + 1, b[i + 1][0] + 1, b[i + 1][1] + 1, b[i + 2][0] + 1, b[i + 2][1] + 1)


def main():
	(n, m) = map(int, input().split())
	ig = [input() for _ in range(n)]
	g = [[False] * (m + 1) for _ in range(n + 1)]
	ans = []

	def swap(a, b):
		g[a][b] = not g[a][b]

	def out(a, b, c, d, e, f):
		ans.append(' '.join(map(str, [a, b, c, d, e, f])))
		swap(a, b)
		swap(c, d)
		swap(e, f)
	for i in range(n):
		for j in range(m):
			if ig[i][j] == '1':
				g[i + 1][j + 1] = True
	for i in range(1, n - 1):
		for j in range(1, m):
			if g[i][j]:
				if g[i][j + 1]:
					out(i, j, i, j + 1, i + 1, j + 1)
				else:
					out(i, j, i + 1, j, i + 1, j + 1)
			if g[i][j + 1]:
				out(i, j + 1, i + 1, j, i + 1, j + 1)
	for i in range(1, m - 1):
		if g[n - 1][i]:
			if g[n][i]:
				out(n - 1, i, n, i, n - 1, i + 1)
			else:
				out(n - 1, i, n, i + 1, n - 1, i + 1)
		elif g[n][i]:
			out(n, i, n - 1, i + 1, n, i + 1)
	rest = [[n - 1, m - 1], [n - 1, m], [n, m - 1], [n, m]]

	def three():
		cur = []
		for (cx, cy) in rest:
			if g[cx][cy]:
				cur.append(cx)
				cur.append(cy)
		out(*cur)

	def two():
		flag = 1
		cur = []
		for (cx, cy) in rest:
			if g[cx][cy]:
				if flag:
					flag -= 1
					cur.append(cx)
					cur.append(cy)
			else:
				cur.append(cx)
				cur.append(cy)
		out(*cur)
		three()

	def one():
		flag = 2
		cur = []
		for (cx, cy) in rest:
			if not g[cx][cy]:
				if flag:
					flag -= 1
					cur.append(cx)
					cur.append(cy)
			else:
				cur.append(cx)
				cur.append(cy)
		out(*cur)
		two()

	def four():
		flag = 3
		cur = []
		for (cx, cy) in rest:
			if flag:
				flag -= 1
				cur.append(cx)
				cur.append(cy)
		out(*cur)
		one()
	mx = 0
	for i in rest:
		if g[i[0]][i[1]]:
			mx += 1
	if mx == 1:
		one()
	elif mx == 2:
		two()
	elif mx == 3:
		three()
	elif mx == 4:
		four()
	print(len(ans))
	for i in ans:
		print(i)
t = int(input())
for _ in range(t):
	main()


for _ in range(int(input())):
	(n, m) = [int(x) for x in input().split(' ')]
	a = []
	for i in range(n):
		ls = [int(x) for x in input()]
		a.append(list(ls))
	anss = []
	b1 = n % 2 == 0
	b2 = m % 2 == 0

	def flip(i, j):
		global a
		a[i][j] = 1 - a[i][j]

	def L0(i, j):
		global anss
		global a
		anss.append((i, j, i + 1, j, i, j + 1))

	def L1(i, j):
		global anss
		global a
		anss.append((i, j, i + 1, j + 1, i, j + 1))

	def L2(i, j):
		global anss
		global a
		anss.append((i + 1, j + 1, i + 1, j, i, j + 1))

	def L3(i, j):
		global anss
		global a
		anss.append((i, j, i + 1, j, i + 1, j + 1))

	def solve11(i, j):
		global a
		global anss
		if a[i][j]:
			anss.append((i, j, i, j + 1, i + 1, j))
			flip(i, j)
			flip(i, j + 1)
			flip(i + 1, j)
		return

	def solve12(i, j):
		global anss
		global a
		if a[i][j] and a[i][j + 1]:
			anss.append((i, j, i, j + 1, i + 1, j))
			flip(i, j)
			flip(i, j + 1)
			flip(i + 1, j)
		elif a[i][j]:
			anss.append((i, j, i + 1, j, i + 1, j + 1))
			flip(i, j)
			flip(i + 1, j)
			flip(i + 1, j + 1)
		elif a[i][j + 1]:
			anss.append((i, j + 1, i + 1, j, i + 1, j + 1))
			flip(i, j + 1)
			flip(i + 1, j)
			flip(i + 1, j + 1)
		else:
			pass
		return

	def solve21(i, j):
		global anss
		global a
		if a[i][j] and a[i + 1][j]:
			anss.append((i, j, i + 1, j, i + 1, j + 1))
			flip(i, j)
			flip(i + 1, j)
			flip(i + 1, j + 1)
		elif a[i][j]:
			anss.append((i, j, i, j + 1, i + 1, j + 1))
			flip(i, j)
			flip(i, j + 1)
			flip(i + 1, j + 1)
		elif a[i + 1][j]:
			anss.append((i + 1, j, i + 1, j + 1, i, j + 1))
			flip(i + 1, j)
			flip(i + 1, j + 1)
			flip(i, j + 1)
		else:
			pass
		return

	def solve22(i, j):
		cnt = a[i][j] + a[i + 1][j] + a[i][j + 1] + a[i + 1][j + 1]
		if cnt == 0:
			pass
		elif cnt == 1:
			if a[i][j] == 1:
				L0(i, j)
				L1(i, j)
				L3(i, j)
			elif a[i + 1][j] == 1:
				L0(i, j)
				L2(i, j)
				L3(i, j)
			elif a[i][j + 1] == 1:
				L0(i, j)
				L1(i, j)
				L2(i, j)
			elif a[i + 1][j + 1] == 1:
				L1(i, j)
				L2(i, j)
				L3(i, j)
			else:
				assert 0
		elif cnt == 2:
			crossSum = max(a[i][j] + a[i + 1][j + 1], a[i + 1][j] + a[i][j + 1])
			if crossSum == 1:
				if a[i][j] == 0:
					L0(i, j)
				if a[i + 1][j] == 0:
					L3(i, j)
				if a[i][j + 1] == 0:
					L1(i, j)
				if a[i + 1][j + 1] == 0:
					L2(i, j)
			elif crossSum == 2:
				if a[i][j] == 1:
					L0(i, j)
				if a[i + 1][j] == 1:
					L3(i, j)
				if a[i][j + 1] == 1:
					L1(i, j)
				if a[i + 1][j + 1] == 1:
					L2(i, j)
			else:
				assert 0
		elif cnt == 3:
			if a[i][j] == 0:
				L2(i, j)
			elif a[i + 1][j] == 0:
				L1(i, j)
			elif a[i][j + 1] == 0:
				L3(i, j)
			elif a[i + 1][j + 1] == 0:
				L0(i, j)
			else:
				assert 0
		else:
			L0(i, j)
			L1(i, j)
			L2(i, j)
			L3(i, j)
		a[i][j] = 0
		a[i + 1][j] = 0
		a[i][j + 1] = 0
		a[i + 1][j + 1] = 0
		return
	if b1 and b2:
		i = 0
		while i < len(a) - 2:
			j = 0
			while j < len(a[0]):
				solve12(i, j)
				j += 2
			i += 1
		j = 0
		while j < len(a[0]):
			solve22(i, j)
			j += 2
	elif b1:
		j = 0
		while j < len(a[0]) - 2:
			i = 0
			while i < len(a):
				solve21(i, j)
				i += 2
			j += 1
		i = 0
		while i < len(a):
			solve22(i, j)
			i += 2
	elif b2:
		i = 0
		while i < len(a) - 2:
			j = 0
			while j < len(a[0]):
				solve12(i, j)
				j += 2
			i += 1
		j = 0
		while j < len(a[0]):
			solve22(i, j)
			j += 2
	else:
		i = 0
		while i < len(a) - 2:
			solve11(i, 0)
			j = 1
			while j < len(a[0]):
				solve12(i, j)
				j += 2
			i += 1
		j = 0
		while j < len(a[0]) - 2:
			solve21(i, j)
			j += 1
		solve22(i, j)
	print(len(anss))
	for x in anss:
		for y in x:
			print(int(y) + 1, end=' ')
		print()


import math
a = int(input())
arr = []
(n, m) = (0, 0)

def flip(i):
	if i == 0:
		return 1
	return 0

def p(ans):
	print(len(ans))
	for i in range(0, len(ans)):
		for j in range(0, len(ans[0])):
			ans[i][j] = ans[i][j] + 1
	for i in ans:
		print(' '.join(map(str, i)))

def o1(temp):
	temp.append([n - 2, m - 2, n - 2, m - 1, n - 1, m - 1])
	arr[n - 2][m - 2] = flip(arr[n - 2][m - 2])
	arr[n - 2][m - 1] = flip(arr[n - 2][m - 1])
	arr[n - 1][m - 1] = flip(arr[n - 1][m - 1])

def o2(temp):
	temp.append([n - 1, m - 1, n - 2, m - 1, n - 1, m - 2])
	arr[n - 1][m - 1] = flip(arr[n - 1][m - 1])
	arr[n - 2][m - 1] = flip(arr[n - 2][m - 1])
	arr[n - 1][m - 2] = flip(arr[n - 1][m - 2])

def o3(temp):
	temp.append([n - 1, m - 1, n - 1, m - 2, n - 2, m - 2])
	arr[n - 1][m - 1] = flip(arr[n - 1][m - 1])
	arr[n - 1][m - 2] = flip(arr[n - 1][m - 2])
	arr[n - 2][m - 2] = flip(arr[n - 2][m - 2])

def o4(temp):
	temp.append([n - 2, m - 2, n - 1, m - 2, n - 2, m - 1])
	arr[n - 2][m - 2] = flip(arr[n - 2][m - 2])
	arr[n - 1][m - 2] = flip(arr[n - 1][m - 2])
	arr[n - 2][m - 1] = flip(arr[n - 2][m - 1])
for i in range(a):
	(n, m) = map(int, input().split())
	arr = []
	for i in range(n):
		s = input()
		arr.append([int(i) for i in s])
	ans = []
	for i in range(0, n - 2):
		for j in range(0, m):
			if arr[i][j] == 1 and j < m - 1:
				ans.append([i, j, i, j + 1, i + 1, j])
				arr[i][j] = flip(arr[i][j])
				arr[i][j + 1] = flip(arr[i][j + 1])
				arr[i + 1][j] = flip(arr[i + 1][j])
			elif arr[i][j] == 1:
				ans.append([i, j, i + 1, j, i + 1, j - 1])
				arr[i][j] = flip(arr[i][j])
				arr[i + 1][j] = flip(arr[i + 1][j])
				arr[i + 1][j - 1] = flip(arr[i + 1][j - 1])
	for j in range(0, m - 2):
		for i in range(n - 2, n):
			if arr[i][j] == 1:
				if i == n - 2:
					ans.append([i, j, i, j + 1, i + 1, j + 1])
					arr[i][j] = flip(arr[i][j])
					arr[i][j + 1] = flip(arr[i][j + 1])
					arr[i + 1][j + 1] = flip(arr[i + 1][j + 1])
				else:
					ans.append([i, j, i, j + 1, i - 1, j + 1])
					arr[i][j] = flip(arr[i][j])
					arr[i][j + 1] = flip(arr[i][j + 1])
					arr[i - 1][j + 1] = flip(arr[i - 1][j + 1])
	su = 0
	for i in range(n - 2, n):
		for j in range(m - 2, m):
			su = su + arr[i][j]
	if su == 0:
		p(ans)
	if su == 1:
		if arr[n - 2][m - 2] == 1:
			o1(ans)
			o3(ans)
			o4(ans)
			p(ans)
		if arr[n - 1][m - 1] == 1:
			o1(ans)
			o2(ans)
			o3(ans)
			p(ans)
		if arr[n - 2][m - 1] == 1:
			o2(ans)
			o1(ans)
			o4(ans)
			p(ans)
		if arr[n - 1][m - 2] == 1:
			o4(ans)
			o2(ans)
			o3(ans)
			p(ans)
	if su == 2:
		if arr[n - 2][m - 2] == 1 and arr[n - 2][m - 1] == 1:
			o2(ans)
			o3(ans)
		if arr[n - 2][m - 2] == 1 and arr[n - 1][m - 2] == 1:
			o1(ans)
			o2(ans)
		if arr[n - 1][m - 1] == 1 and arr[n - 2][m - 1] == 1:
			o3(ans)
			o4(ans)
		if arr[n - 1][m - 1] == 1 and arr[n - 1][m - 2] == 1:
			o4(ans)
			o1(ans)
		if arr[n - 1][m - 1] == 1 and arr[n - 2][m - 2] == 1:
			o2(ans)
			o4(ans)
		if arr[n - 2][m - 1] == 1 and arr[n - 1][m - 2] == 1:
			o1(ans)
			o3(ans)
		p(ans)
	if su == 4:
		o2(ans)
		o1(ans)
		o3(ans)
		o4(ans)
		p(ans)
	if su == 3:
		temp = []
		for i in range(n - 2, n):
			for j in range(m - 2, m):
				if arr[i][j] == 1:
					temp.append(i)
					temp.append(j)
		ans.append(temp)
		p(ans)


import sys
from functools import lru_cache, cmp_to_key
from heapq import merge, heapify, heappop, heappush
from math import *
from collections import defaultdict as dd, deque, Counter as C
from itertools import combinations as comb, permutations as perm
from bisect import bisect_left as bl, bisect_right as br, bisect
from time import perf_counter
from fractions import Fraction
import copy
import time
starttime = time.time()
mod = int(pow(10, 9) + 7)
mod2 = 998244353

def data():
	return sys.stdin.readline().strip()

def out(*var, end='\n'):
	sys.stdout.write(' '.join(map(str, var)) + end)

def L():
	return list(sp())

def sl():
	return list(ssp())

def sp():
	return map(int, data().split())

def ssp():
	return map(str, data().split())

def l1d(n, val=0):
	return [val for i in range(n)]

def l2d(n, m, val=0):
	return [l1d(n, val) for j in range(m)]
try:
	sys.stdin = open('input.txt', 'r')
except:
	pass

def pmat(A):
	for ele in A:
		print(*ele, end='\n')

def seive():
	prime = [1 for i in range(10 ** 6 + 1)]
	prime[0] = 0
	prime[1] = 0
	for i in range(10 ** 6 + 1):
		if prime[i]:
			for j in range(2 * i, 10 ** 6 + 1, i):
				prime[j] = 0
	return prime
for _ in range(int(input())):
	(m, n) = map(int, input().split())
	A = [[0] * (n + 1)] + [[0] + list(map(int, list(input()))) for _ in range(m)]
	ans = []
	for i in range(1, m - 1):
		for j in range(1, n + 1):
			if A[i][j]:
				ans.append([i, j, i + 1, j, i + 1, j + 1 if j < n else j - 1])
				A[i][j] ^= 1
				A[i + 1][j] ^= 1
				A[i + 1][j + 1 if j < n else j - 1] ^= 1
	for j in range(1, n - 1):
		if A[m - 1][j] and A[m][j]:
			ans.append([m - 1, j, m, j, m - 1, j + 1])
			A[m - 1][j] ^= 1
			A[m][j] ^= 1
			A[m - 1][j + 1] ^= 1
		elif A[m - 1][j]:
			ans.append([m - 1, j, m - 1, j + 1, m, j + 1])
			A[m - 1][j] ^= 1
			A[m - 1][j + 1] ^= 1
			A[m][j + 1] ^= 1
		elif A[m][j]:
			ans.append([m, j, m, j + 1, m - 1, j + 1])
			A[m][j] ^= 1
			A[m][j + 1] ^= 1
			A[m - 1][j + 1] ^= 1
	if A[m - 1][n - 1] ^ A[m - 1][n] ^ A[m][n - 1]:
		ans.append([m - 1, n - 1, m - 1, n, m, n - 1])
	if A[m - 1][n - 1] ^ A[m][n - 1] ^ A[m][n]:
		ans.append([m - 1, n - 1, m, n - 1, m, n])
	if A[m][n - 1] ^ A[m][n] ^ A[m - 1][n]:
		ans.append([m, n - 1, m, n, m - 1, n])
	if A[m][n] ^ A[m - 1][n] ^ A[m - 1][n - 1]:
		ans.append([m, n, m - 1, n, m - 1, n - 1])
	print(len(ans))
	for a in ans:
		print(*a)
endtime = time.time()


from sys import stdin, stdout
input = stdin.readline

def f1(a, b, c, d):
	global ans
	ans.append((a[1], a[2], b[1], b[2], c[1], c[2]))
	ans.append((a[1], a[2], b[1], b[2], d[1], d[2]))
	ans.append((a[1], a[2], d[1], d[2], c[1], c[2]))

def f2(a, b, c, d):
	global ans
	ans.append((a[1], a[2], b[1], b[2], d[1], d[2]))
	ans.append((a[1], a[2], d[1], d[2], c[1], c[2]))

def f3(a, b, c, d):
	global ans
	ans.append((a[1], a[2], d[1], d[2], c[1], c[2]))
t = int(input())
for _ in range(t):
	(n, m) = map(int, input().split())
	mat = [[0 for x in range(m)] for y in range(n)]
	for i in range(n):
		x = input()
		for j in range(m):
			mat[i][j] = int(x[j])
	ans = []
	for i in range(n - 1):
		for j in range(m - 1):
			if i == n - 2 and j == m - 2:
				arr = [(mat[i][j], i, j), (mat[i + 1][j], i + 1, j), (mat[i][j + 1], i, j + 1), (mat[i + 1][j + 1], i + 1, j + 1)]
				arr = sorted(arr, key=lambda x: x[0], reverse=True)
				c = 0
				for k in arr:
					if k[0]:
						c += 1
				if c == 0:
					continue
				elif c == 1:
					f1(arr[0], arr[1], arr[2], arr[3])
				elif c == 2:
					f2(arr[3], arr[0], arr[1], arr[2])
				elif c == 3:
					f3(arr[2], arr[3], arr[1], arr[0])
				else:
					ans.append((i + 1, j + 1, i, j + 1, i + 1, j))
					f1(arr[0], arr[1], arr[2], arr[3])
				continue
			if j == m - 2:
				if mat[i][j] and mat[i][j + 1]:
					ans.append((i, j, i, j + 1, i + 1, j))
				elif not mat[i][j] and mat[i][j + 1]:
					ans.append((i + 1, j + 1, i, j + 1, i + 1, j))
				elif mat[i][j] and (not mat[i][j + 1]):
					ans.append((i, j, i + 1, j, i + 1, j + 1))
				else:
					continue
				for k in range(0, 6, 2):
					mat[ans[-1][k]][ans[-1][k + 1]] ^= 1
				continue
			if i == n - 2:
				if mat[i][j] and mat[i + 1][j]:
					ans.append((i, j, i + 1, j, i, j + 1))
				elif not mat[i][j] and mat[i + 1][j]:
					ans.append((i + 1, j + 1, i, j + 1, i + 1, j))
				elif mat[i][j] and (not mat[i + 1][j]):
					ans.append((i, j, i, j + 1, i + 1, j + 1))
				else:
					continue
				for k in range(0, 6, 2):
					mat[ans[-1][k]][ans[-1][k + 1]] ^= 1
				continue
			if mat[i][j]:
				ans.append((i, j, i, j + 1, i + 1, j))
			else:
				continue
			for k in range(0, 6, 2):
				mat[ans[-1][k]][ans[-1][k + 1]] ^= 1
	stdout.write(str(len(ans)) + '\n')
	for i in ans:
		for j in i:
			stdout.write(str(j + 1) + ' ')
		stdout.write('\n')


t = int(input())
for _ in range(t):
	(n, m) = map(int, input().split())
	s = []
	for _ in range(n):
		s.append(list(input()))
	o = []

	def R(x):
		global s
		for z in x:
			if s[z[0]][z[1]] == '1':
				s[z[0]][z[1]] = '0'
			else:
				s[z[0]][z[1]] = '1'
	for x in range(n - 2):
		for y in range(m - 1):
			a = []
			if s[x][y] == '1':
				a.append((x, y))
			if s[x][y + 1] == '1':
				a.append((x, y + 1))
			if not a:
				continue
			if (x + 1, y + 1) not in a and len(a) < 3:
				a.append((x + 1, y + 1))
			if (x + 1, y) not in a and len(a) < 3:
				a.append((x + 1, y))
			o.append(a)
			R(a)
	for y in range(m - 2):
		x = n - 2
		a = []
		if s[x][y] == '1':
			a.append((x, y))
		if s[x + 1][y] == '1':
			a.append((x + 1, y))
		if not a:
			continue
		if (x + 1, y + 1) not in a and len(a) < 3:
			a.append((x + 1, y + 1))
		if (x, y + 1) not in a and len(a) < 3:
			a.append((x, y + 1))
		o.append(a)
		R(a)
	A = ((n - 2, m - 2), (n - 1, m - 2), (n - 2, m - 1), (n - 1, m - 1))
	while True:
		z = []
		for x in A:
			if s[x[0]][x[1]] == '1':
				z.append(x)
		if len(z) > 0:
			z1 = z[:]
			if len(z) == 4:
				z1 = z1[:3]
			elif len(z) == 2:
				z1 = [z1[0]]
			for r in A:
				if len(z1) < 3 and r not in z:
					z1.append(r)
			o.append(z1)
			R(z1)
		else:
			break
	print(len(o))
	for b in o:
		print(b[0][0] + 1, b[0][1] + 1, b[1][0] + 1, b[1][1] + 1, b[2][0] + 1, b[2][1] + 1)


import os
import sys
from io import BytesIO, IOBase
import heapq as h
from bisect import bisect_left, bisect_right
import time
from types import GeneratorType
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		import os
		self.os = os
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			self.os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from collections import defaultdict as dd, deque as dq, Counter as dc
import math, string

def getInts():
	return [int(s) for s in input().split()]

def getInt():
	return int(input())

def getStrs():
	return [s for s in input().split()]

def getStr():
	return input()

def listStr():
	return list(input())

def getMat(n):
	return [getInts() for _ in range(n)]
MOD = 10 ** 9 + 7

def solve():
	(N, M) = getInts()
	grid = []
	for n in range(N):
		grid.append([int(s) for s in input()])
	ans = 0
	ops = []

	def solve2(inds, flag=False, flag2=False):
		ret = []
		if not inds:
			return ret
		if len(inds) == 3:
			ret.append((inds[0][0], inds[0][1], inds[1][0], inds[1][1], inds[2][0], inds[2][1]))
			return ret
		if len(inds) == 1:
			neigh1 = (inds[0][0] + (1 if inds[0][0] % 2 == 1 and inds[0][0] < N and (not flag) or (flag and inds[0][0] < N) else -1), inds[0][1] + (1 if inds[0][1] % 2 == 1 and inds[0][1] < M and (not flag2) or (flag2 and inds[0][1] < M) else -1))
			neigh2 = (inds[0][0] + (1 if inds[0][0] % 2 == 1 and inds[0][0] < N and (not flag) or (flag and inds[0][0] < N) else -1), inds[0][1])
			ret.append((inds[0][0], inds[0][1], neigh1[0], neigh1[1], neigh2[0], neigh2[1]))
			new_inds = [neigh1, neigh2]
			x = solve2(new_inds, flag, flag2)
			for el in x:
				ret.append(el)
			return ret
		if len(inds) == 4:
			ret.append((inds[0][0], inds[0][1], inds[1][0], inds[1][1], inds[2][0], inds[2][1]))
			new_inds = [(inds[3][0], inds[3][1])]
			x = solve2(new_inds, flag, flag2)
			for el in x:
				ret.append(el)
			return ret
		if len(inds) == 2:
			if (inds[0][0] + inds[0][1]) % 2 == (inds[1][0] + inds[1][1]) % 2:
				neigh1 = (inds[0][0], inds[0][1] + (1 if inds[0][1] % 2 == 1 and inds[0][1] < M and (not flag2) or (flag2 and inds[0][1] < M) else -1))
				neigh2 = (inds[0][0] + (1 if inds[0][0] % 2 == 1 and inds[0][0] < N and (not flag) or (flag and inds[0][0] < N) else -1), inds[0][1])
			else:
				neigh1 = (inds[0][0], inds[0][1] + (1 if inds[0][1] % 2 == 1 and inds[0][1] < M and (not flag2) or (flag2 and inds[0][1] < M) else -1))
				neigh2 = (inds[0][0] + (1 if inds[0][0] % 2 == 1 and inds[0][0] < N and (not flag) or (flag and inds[0][0] < N) else -1), inds[0][1])
				if neigh1 == inds[1]:
					neigh1 = (inds[0][0] + (1 if inds[0][0] % 2 == 1 and inds[0][0] < N and (not flag) or (flag and inds[0][0] < N) else -1), inds[0][1] + (1 if inds[0][1] % 2 == 1 and inds[0][1] < M and (not flag2) or (flag2 and inds[0][1] < M) else -1))
				else:
					neigh2 = (inds[0][0] + (1 if inds[0][0] % 2 == 1 and inds[0][0] < N and (not flag) or (flag and inds[0][0] < N) else -1), inds[0][1] + (1 if inds[0][1] % 2 == 1 and inds[0][1] < M and (not flag2) or (flag2 and inds[0][1] < M) else -1))
			ret.append((inds[0][0], inds[0][1], neigh1[0], neigh1[1], neigh2[0], neigh2[1]))
			new_inds = [inds[1], neigh1, neigh2]
			x = solve2(new_inds, flag, flag2)
			for el in x:
				ret.append(el)
			return ret
	for n in range(N - 1, 1, -1):
		for m in range(M - 1, 1, -1):
			if grid[n][m] == 1:
				inds = (n + 1, m + 1, n, m + 1, n, m)
				ops.append(inds)
				grid[n][m] ^= 1
				grid[n - 1][m] ^= 1
				grid[n - 1][m - 1] ^= 1
		if grid[n][0] * grid[n][1] == 1:
			inds = (n + 1, 1, n + 1, 2, n, 2)
			ops.append(inds)
			grid[n][0] = 0
			grid[n][1] = 0
			grid[n - 1][1] ^= 1
		elif grid[n][0] == 1:
			inds = (n + 1, 1, n, 1, n, 2)
			ops.append(inds)
			grid[n][0] = 0
			grid[n - 1][0] ^= 1
			grid[n - 1][1] ^= 1
		elif grid[n][1] == 1:
			inds = (n + 1, 2, n, 2, n, 1)
			ops.append(inds)
			grid[n][1] = 0
			grid[n - 1][1] ^= 1
			grid[n - 1][0] ^= 1
	for m in range(M - 1, 1, -1):
		if grid[0][m] * grid[1][m] == 1:
			inds = (1, m + 1, 2, m + 1, 2, m)
			ops.append(inds)
			grid[0][m] = 0
			grid[1][m] = 0
			grid[1][m - 1] ^= 1
		elif grid[0][m] == 1:
			inds = (1, m + 1, 1, m, 2, m)
			ops.append(inds)
			grid[0][m] = 0
			grid[0][m - 1] ^= 1
			grid[1][m - 1] ^= 1
		elif grid[1][m] == 1:
			inds = (2, m + 1, 2, m, 1, m)
			ops.append(inds)
			grid[1][m] = 0
			grid[1][m - 1] ^= 1
			grid[0][m - 1] ^= 1
	inds = []
	for i in range(2):
		for j in range(2):
			if grid[i][j] == 1:
				inds.append((i + 1, j + 1))
				grid[i][j] = 0
	tmp = solve2(inds)
	ans += len(tmp)
	for t in tmp:
		ops.append(t)
	print(len(ops))
	for op in ops:
		print(*op)
	return
for _ in range(getInt()):
	solve()


from itertools import chain as _chain

def how_to_make_zeros(matrix):
	n = len(matrix)
	m = len(matrix[0])
	if n % 2 == 0 and m % 2 == 0:
		for y in range(0, n, 2):
			for x in range(0, m, 2):
				yield from _get_moves_to_invert_2x2(x, y, matrix)
	elif m % 3 != 0:
		if m % 3 == 2:
			offset = 2
		else:
			assert m % 3 == 1
			offset = 4
		odd = [row[:offset] for row in matrix]
		odd = tuple(zip(*odd))
		moves_for_odd = how_to_make_zeros(odd)
		moves_for_odd = map(lambda move: tuple(((y, x) for (x, y) in move)), moves_for_odd)
		yield from moves_for_odd
		remain = [row[offset:] for row in matrix]
		moves_for_remain = how_to_make_zeros(remain)
		moves_for_remain = (tuple(((x + offset, y) for (x, y) in move)) for move in moves_for_remain)
		yield from moves_for_remain
	else:
		for y in range(n):
			for x in range(0, m, 3):
				yield from _get_moves_to_invert_3x1(x, y, matrix)

def _get_moves_to_invert_cell(pos):
	(x, y) = pos
	inv_x = x - 1 if x != 0 else x + 1
	inv_y = y - 1 if y != 0 else y + 1
	return [((x, y), (inv_x, y), (inv_x, inv_y)), ((x, y), (x, inv_y), (inv_x, inv_y)), ((x, y), (inv_x, y), (x, inv_y))]

def _get_moves_to_invert_2x2(x, y, matrix):
	get_val = lambda pos: matrix[pos[1]][pos[0]]
	poses = [(x, y), (x + 1, y), (x, y + 1), (x + 1, y + 1)]
	active_poses = tuple(filter(lambda pos: get_val(pos) == '1', poses))
	active_n = len(active_poses)
	dead_poses = tuple(filter(lambda pos: get_val(pos) == '0', poses))
	if active_n == 0:
		moves = []
	elif active_n == 1:
		((x1, y1),) = active_poses
		moves = _get_moves_to_invert_cell((x1, y1))
	elif active_n == 2:
		(act1, act2) = active_poses
		(dead1, dead2) = dead_poses
		moves = [(dead1, dead2, act1), (dead1, dead2, act2)]
	elif active_n == 3:
		moves = [active_poses]
	else:
		assert active_n == 4
		poses = set(poses)
		moves = [poses - {pos} for pos in poses]
		moves = list(map(tuple, moves))
	return moves

def _get_moves_to_invert_3x1(x, y, matrix):
	inv_y = y - 1 if y != 0 else y + 1
	active_xs = tuple(filter(lambda x: matrix[y][x] == '1', (x, x + 1, x + 2)))
	active_n = len(active_xs)
	if active_n == 0:
		moves = []
	elif active_n == 1:
		(x1,) = active_xs
		moves = _get_moves_to_invert_cell((x1, y))
	elif active_n == 2:
		(x1, x2) = active_xs
		if x1 + 1 == x2:
			moves = [((x1, inv_y), (x2, inv_y), (x1, y)), ((x1, inv_y), (x2, inv_y), (x2, y))]
		else:
			assert x1 + 2 == x2
			mid_x = x1 + 1
			moves = [((mid_x, y), (mid_x, inv_y), (x1, y)), ((mid_x, y), (mid_x, inv_y), (x2, y))]
	elif active_n == 3:
		moves = [((x + 2, y), (x + 1, y), (x + 1, inv_y)), ((x + 1, y), (x, inv_y), (x, y)), ((x + 1, y), (x, inv_y), (x + 1, inv_y))]
	return moves

def main():
	(t,) = _read_ints()
	for i_t in range(t):
		(n, m) = _read_ints()
		matrix = tuple((input() for i in range(n)))
		moves = list(how_to_make_zeros(matrix))
		print(len(moves))
		for move in moves:
			move = tuple(((y + 1, x + 1) for (x, y) in move))
			print(*_chain.from_iterable(move))

def _read_ints():
	return map(int, input().split())
main()


from bisect import *
from collections import *
from math import gcd, ceil, sqrt, floor, inf
from heapq import *
from itertools import *
from operator import add, mul, sub, xor, truediv, floordiv
from functools import *
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def RL():
	return map(int, sys.stdin.readline().rstrip().split())

def RLL():
	return list(map(int, sys.stdin.readline().rstrip().split()))

def N():
	return int(input())
from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc
farr = [1]
ifa = []

def fact(x, mod=0):
	if mod:
		while x >= len(farr):
			farr.append(farr[-1] * len(farr) % mod)
	else:
		while x >= len(farr):
			farr.append(farr[-1] * len(farr))
	return farr[x]

def ifact(x, mod):
	global ifa
	ifa.append(pow(farr[-1], mod - 2, mod))
	for i in range(x, 0, -1):
		ifa.append(ifa[-1] * i % mod)
	ifa = ifa[::-1]

def per(i, j, mod=0):
	if i < j:
		return 0
	if not mod:
		return fact(i) // fact(i - j)
	return farr[i] * ifa[i - j] % mod

def com(i, j, mod=0):
	if i < j:
		return 0
	if not mod:
		return per(i, j) // fact(j)
	return per(i, j, mod) * ifa[j] % mod

def catalan(n):
	return com(2 * n, n) // (n + 1)

def linc(f, t, l, r):
	while l < r:
		mid = (l + r) // 2
		if t > f(mid):
			l = mid + 1
		else:
			r = mid
	return l

def rinc(f, t, l, r):
	while l < r:
		mid = (l + r + 1) // 2
		if t < f(mid):
			r = mid - 1
		else:
			l = mid
	return l

def ldec(f, t, l, r):
	while l < r:
		mid = (l + r) // 2
		if t < f(mid):
			l = mid + 1
		else:
			r = mid
	return l

def rdec(f, t, l, r):
	while l < r:
		mid = (l + r + 1) // 2
		if t > f(mid):
			r = mid - 1
		else:
			l = mid
	return l

def isprime(n):
	for i in range(2, int(n ** 0.5) + 1):
		if n % i == 0:
			return False
	return True

def binfun(x):
	c = 0
	for w in arr:
		c += ceil(w / x)
	return c

def lowbit(n):
	return n & -n

def inverse(a, m):
	a %= m
	if a <= 1:
		return a
	return (1 - inverse(m, a) * m) // a % m

class BIT:

	def __init__(self, arr):
		self.arr = arr
		self.n = len(arr) - 1

	def update(self, x, v):
		while x <= self.n:
			self.arr[x] += v
			x += x & -x

	def query(self, x):
		ans = 0
		while x:
			ans += self.arr[x]
			x &= x - 1
		return ans

class DSU:

	def __init__(self, n):
		self.c = [-1] * n

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def find(self, x):
		if self.c[x] < 0:
			return x
		self.c[x] = self.find(self.c[x])
		return self.c[x]

	def union(self, u, v):
		(u, v) = (self.find(u), self.find(v))
		if u == v:
			return False
		if self.c[u] < self.c[v]:
			(u, v) = (v, u)
		self.c[u] += self.c[v]
		self.c[v] = u
		return True

	def size(self, x):
		return -self.c[self.find(x)]

class UFS:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.ranks = [0] * n

	def find(self, x):
		if x != self.parent[x]:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, u, v):
		(pu, pv) = (self.find(u), self.find(v))
		if pu == pv:
			return False
		if self.ranks[pu] >= self.ranks[pv]:
			self.parent[pv] = pu
			if self.ranks[pv] == self.ranks[pu]:
				self.ranks[pu] += 1
		else:
			self.parent[pu] = pv

def Prime(n):
	c = 0
	prime = []
	flag = [0] * (n + 1)
	for i in range(2, n + 1):
		if not flag[i]:
			prime.append(i)
			c += 1
		for j in range(c):
			if i * prime[j] > n:
				break
			flag[i * prime[j]] = prime[j]
			if i % prime[j] == 0:
				break
	return prime

def dij(s, graph):
	d = {}
	d[s] = 0
	heap = [(0, s)]
	seen = set()
	while heap:
		(dis, u) = heappop(heap)
		if u in seen:
			continue
		for v in graph[u]:
			if v not in d or d[v] > d[u] + graph[u][v]:
				d[v] = d[u] + graph[u][v]
				heappush(heap, (d[v], v))
	return d

def GP(it):
	return [(ch, len(list(g))) for (ch, g) in groupby(it)]

class DLN:

	def __init__(self, val):
		self.val = val
		self.pre = None
		self.next = None

class Trie:

	def __init__(self, d):
		if d >= 0:
			self.left = Trie(d - 1)
		else:
			self.right = Trie(d - 1)
		self.c = 0

	def put(self, x, i):
		if i == -1:
			self.c = 1
			return
		if x & 1 << i:
			self.left.put(x, i - 1)
		else:
			self.right.put(x, i - 1)

def con(i, j, x):
	i += 1
	j += 1
	if x == 0:
		return [i, j, i, j + 1, i + 1, j]
	if x == 1:
		return [i, j, i, j + 1, i + 1, j + 1]
	if x == 2:
		return [i, j, i + 1, j, i + 1, j + 1]
	if x == 3:
		return [i, j + 1, i + 1, j, i + 1, j + 1]

def f(i, j):
	if i < n - 1 and j < m - 1:
		res = a[i][j] + a[i][j + 1] + a[i + 1][j] + a[i + 1][j + 1]
		if res == '1111':
			for d in range(4):
				ans.append(con(i, j, d))
		elif res == '1110':
			ans.append(con(i, j, 0))
		elif res == '1101':
			ans.append(con(i, j, 1))
		elif res == '1011':
			ans.append(con(i, j, 2))
		elif res == '0111':
			ans.append(con(i, j, 3))
		elif res == '1000':
			for d in range(4):
				if d != 3:
					ans.append(con(i, j, d))
		elif res == '0100':
			for d in range(4):
				if d != 2:
					ans.append(con(i, j, d))
		elif res == '0010':
			for d in range(4):
				if d != 1:
					ans.append(con(i, j, d))
		elif res == '0001':
			for d in range(4):
				if d != 0:
					ans.append(con(i, j, d))
		elif res == '1100':
			ans.append(con(i, j, 2))
			ans.append(con(i, j, 3))
		elif res == '1010':
			ans.append(con(i, j, 1))
			ans.append(con(i, j, 3))
		elif res == '0101':
			ans.append(con(i, j, 0))
			ans.append(con(i, j, 2))
		elif res == '0011':
			ans.append(con(i, j, 0))
			ans.append(con(i, j, 1))
		elif res == '1001':
			ans.append(con(i, j, 0))
			ans.append(con(i, j, 3))
		elif res == '0110':
			ans.append(con(i, j, 1))
			ans.append(con(i, j, 2))
	elif i == n - 1 and j == m - 1:
		if a[i][j] == '1':
			for d in range(4):
				if d != 0:
					ans.append(con(i - 1, j - 1, d))
	elif i == n - 1:
		tmp = a[i][j] + a[i][j + 1]
		if tmp == '11':
			ans.append(con(i - 1, j, 0))
			ans.append(con(i - 1, j, 1))
		elif tmp == '10':
			for d in range(4):
				if d != 1:
					ans.append(con(i - 1, j, d))
		elif tmp == '01':
			for d in range(4):
				if d != 0:
					ans.append(con(i - 1, j, d))
	else:
		tmp = a[i][j] + a[i + 1][j]
		if tmp == '11':
			ans.append(con(i, j - 1, 0))
			ans.append(con(i, j - 1, 2))
		elif tmp == '10':
			for d in range(4):
				if d != 2:
					ans.append(con(i, j - 1, d))
		elif tmp == '01':
			for d in range(4):
				if d != 0:
					ans.append(con(i, j - 1, d))

def rev(i, j):
	if a[i][j] == '1':
		a[i][j] = '0'
	else:
		a[i][j] = '1'
t = N()
for i in range(t):
	(n, m) = RL()
	a = []
	ans = []
	for i in range(n):
		a.append(list(input()))
	if n & 1 and m & 1:
		if a[n - 1][m - 1] == '1':
			ans.append(con(n - 2, m - 2, 3))
			rev(n - 2, m - 1)
			rev(n - 1, m - 2)
			rev(n - 1, m - 1)
	if n & 1:
		for j in range(0, m - 1, 2):
			tmp = a[n - 1][j] + a[n - 1][j + 1]
			if tmp == '11':
				ans.append(con(n - 2, j, 2))
				rev(n - 2, j)
			elif tmp == '10':
				ans.append(con(n - 2, j, 0))
				rev(n - 2, j)
				rev(n - 2, j + 1)
			elif tmp == '01':
				ans.append(con(n - 2, j, 1))
				rev(n - 2, j)
				rev(n - 2, j + 1)
	if m & 1:
		for i in range(0, n - 1, 2):
			tmp = a[i][m - 1] + a[i + 1][m - 1]
			if tmp == '11':
				ans.append(con(i, m - 2, 1))
				rev(i, m - 2)
			elif tmp == '10':
				ans.append(con(i, m - 2, 0))
				rev(i, m - 2)
				rev(i + 1, m - 2)
			elif tmp == '01':
				ans.append(con(i, m - 2, 2))
				rev(i, m - 2)
				rev(i + 1, m - 2)
	for i in range(0, n - 1, 2):
		for j in range(0, m - 1, 2):
			f(i, j)
	print(len(ans))
	for i in range(len(ans)):
		print(*ans[i])


for _ in range(int(input())):
	(r, c) = map(int, input().split())
	a = []
	b = []
	[a.append(list(input())) for i in range(r)]
	for i in range(r - 2):
		for j in range(c):
			if j == 0 and int(a[i][j]):
				a[i][j] = (int(a[i][j]) + 1) % 2
				a[i + 1][j] = (int(a[i + 1][j]) + 1) % 2
				a[i + 1][j + 1] = (int(a[i + 1][j + 1]) + 1) % 2
				b.append([i + 1, j + 1, i + 2, j + 1, i + 2, j + 2])
			elif int(a[i][j]):
				a[i][j] = (int(a[i][j]) + 1) % 2
				a[i + 1][j] = (int(a[i + 1][j]) + 1) % 2
				a[i + 1][j - 1] = (int(a[i + 1][j - 1]) + 1) % 2
				b.append([i + 1, j + 1, i + 2, j + 1, i + 2, j])
	count = 0
	for i in range(r - 2, r):
		for j in range(c):
			count += int(a[i][j])
	for j in range(c - 1):
		if int(a[r - 2][j]) or int(a[r - 1][j]):
			if int(a[r - 2][j]) and int(a[r - 1][j]):
				count -= 2
				if int(a[r - 2][j + 1]):
					b.append([r, j + 1, r - 1, j + 1, r - 1, j + 2])
					a[r - 2][j + 1] = (int(a[r - 2][j + 1]) + 1) % 2
					count -= 1
				else:
					b.append([r - 1, j + 1, r, j + 1, r, j + 2])
					a[r - 1][j + 1] = (int(a[r - 1][j + 1]) + 1) % 2
					if int(a[r - 1][j + 1]):
						count += a[r - 1][j + 1]
					else:
						count -= 1
			elif int(a[r - 2][j]):
				if count == 1:
					i = r - 2
					b.append([i + 1, j + 1, i + 1, j + 2, i + 2, j + 1])
					b.append([i + 1, j + 1, i + 1, j + 2, i + 2, j + 2])
					b.append([i + 1, j + 1, i + 2, j + 1, i + 2, j + 2])
					break
				else:
					count -= 1
					b.append([r - 1, j + 1, r - 1, j + 2, r, j + 2])
					a[r - 2][j + 1] = (int(a[r - 2][j + 1]) + 1) % 2
					a[r - 1][j + 1] = (int(a[r - 1][j + 1]) + 1) % 2
					count += a[r - 1][j + 1] + a[r - 2][j + 1]
			elif count == 1:
				n = r
				b.append([n, j + 1, n, j + 2, n - 1, j + 1])
				b.append([n, j + 1, n, j + 2, n - 1, j + 2])
				b.append([n, j + 1, n - 1, j + 1, n - 1, j + 2])
				break
			else:
				count -= 1
				b.append([r, j + 1, r, j + 2, r - 1, j + 2])
				a[r - 2][j + 1] = (int(a[r - 2][j + 1]) + 1) % 2
				a[r - 1][j + 1] = (int(a[r - 1][j + 1]) + 1) % 2
				count += a[r - 1][j + 1] + a[r - 2][j + 1]
	if int(a[-1][-1]) and int(a[-2][-1]):
		b.append([r, c - 1, r - 1, c, r, c])
		b.append([r - 1, c - 1, r, c - 1, r, c])
		b.append([r - 1, c - 1, r - 1, c, r, c - 1])
		b.append([r, c, r, c - 1, r - 1, c])
	elif int(a[-1][-1]):
		i = r - 1
		j = c - 1
		b.append([i + 1, j + 1, i, j + 1, i + 1, j])
		b.append([i, j + 1, i + 1, j + 1, i, j])
		b.append([i + 1, j, i + 1, j + 1, i, j])
	elif int(a[-2][-1]):
		b.append([r - 1, c - 1, r - 1, c, r, c])
		b.append([r - 1, c, r - 1, c - 1, r, c - 1])
		b.append([r - 1, c, r, c, r, c - 1])
	print(len(b))
	for i in b:
		print(*i)


import sys
from functools import lru_cache, cmp_to_key
from heapq import merge, heapify, heappop, heappush, nsmallest
from math import ceil, floor, gcd, fabs, factorial, fmod, sqrt, inf
from collections import defaultdict as dd, deque, Counter as C
from itertools import combinations as comb, permutations as perm
from bisect import bisect_left as bl, bisect_right as br, bisect
from time import perf_counter
from fractions import Fraction
from decimal import Decimal
mod = pow(10, 9) + 7

def data():
	return sys.stdin.readline().strip()

def out(var):
	sys.stdout.write(str(var) + '\n')

def outa(*var, end='\n'):
	sys.stdout.write(' '.join(map(str, var)) + end)

def l():
	return list(sp())

def sl():
	return list(ssp())

def sp():
	return map(int, data().split())

def ssp():
	return map(str, data().split())

def l1d(n, val=0):
	return [val for i in range(n)]

def l2d(n, m, val=0):
	return [l1d(n, val) for j in range(m)]

def perform(z, o):
	answer.append([])
	for (first, second) in nei:
		if z and mat[first][second] == '0':
			answer[-1].append((first + 1, second + 1))
			z -= 1
			mat[first][second] = '1'
		elif o and mat[first][second] == '1':
			answer[-1].append((first + 1, second + 1))
			o -= 1
			mat[first][second] = '0'
for _ in range(int(data())):
	(n, m) = sp()
	mat = [list(data()) for __ in range(n)]
	answer = []
	if n & 1 or m & 1:
		i = 0
		j = m - 1
		while i < n:
			if mat[i][j] == mat[i + 1][j] == '0':
				i += (1, 2)[i != n - 3]
				continue
			answer.append([])
			if mat[i][j] == '1':
				mat[i][j] = '0'
				answer[-1].append([i + 1, j + 1])
			if mat[i + 1][j] == '1':
				mat[i + 1][j] = '0'
				answer[-1].append([i + 2, j + 1])
			if len(answer[-1]) == 1:
				answer[-1].append([i + 1, j])
				answer[-1].append([i + 2, j])
				mat[i][j - 1] = ('0', '1')[mat[i][j - 1] == '0']
				mat[i + 1][j - 1] = ('0', '1')[mat[i + 1][j - 1] == '0']
			elif len(answer[-1]) == 2:
				answer[-1].append([i + 2, j])
				mat[i + 1][j - 1] = ('0', '1')[mat[i + 1][j - 1] == '0']
			i += (1, 2)[i != n - 3]
		j = 0
		i = n - 1
		while j < m:
			if mat[i][j] == mat[i][j + 1] == '0':
				j += (1, 2)[j != m - 3]
				continue
			answer.append([])
			if mat[i][j] == '1':
				mat[i][j] = '0'
				answer[-1].append([i + 1, j + 1])
			if mat[i][j + 1] == '1':
				mat[i][j + 1] = '0'
				answer[-1].append([i + 1, j + 2])
			if len(answer[-1]) == 1:
				answer[-1].append([i, j + 1])
				answer[-1].append([i, j + 2])
				mat[i - 1][j] = ('0', '1')[mat[i - 1][j] == '0']
				mat[i - 1][j + 1] = ('0', '1')[mat[i - 1][j + 1] == '0']
			elif len(answer[-1]) == 2:
				answer[-1].append([i, j + 2])
				mat[i - 1][j + 1] = ('0', '1')[mat[i - 1][j + 1] == '0']
			j += (1, 2)[j != m - 3]
	i = 0
	while i < n:
		j = 0
		while j < m:
			nei = [[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]]
			j += (1, 2)[j != m - 3]
			cnt = 0
			for (u, v) in nei:
				cnt += int(mat[u][v])
			if cnt == 0:
				continue
			if cnt == 1:
				perform(2, 1)
				perform(2, 1)
				perform(0, 3)
			elif cnt == 2:
				perform(2, 1)
				perform(0, 3)
			elif cnt == 3:
				perform(0, 3)
			else:
				perform(0, 3)
				perform(2, 1)
				perform(2, 1)
				perform(0, 3)
		i += (1, 2)[i != n - 3]
	out(len(answer))
	for i in answer:
		for (a, b) in i:
			outa(a, b, end=' ')
		outa()


t = int(input())
for test in range(t):
	[n, m] = list(map(int, input().rstrip().split()))
	g = [[0 for _ in range(m)] for _ in range(n)]
	for i in range(n):
		s = input()
		for j in range(m):
			g[i][j] = int(s[j])
	o = 0
	op = list()
	for i in range(n - 2):
		for j in range(m - 2):
			if g[i][j] == 1:
				o += 1
				op.append([i, j, i + 1, j, i, j + 1])
				g[i + 1][j] = 1 - g[i + 1][j]
				g[i][j + 1] = 1 - g[i][j + 1]
	for i in range(n - 2):
		if g[i][m - 2] == 1:
			o += 1
			if g[i][m - 1] == 1:
				op.append([i, m - 2, i, m - 1, i + 1, m - 2])
				g[i + 1][m - 2] = 1 - g[i + 1][m - 2]
			else:
				op.append([i, m - 2, i + 1, m - 1, i + 1, m - 2])
				g[i + 1][m - 2] = 1 - g[i + 1][m - 2]
				g[i + 1][m - 1] = 1 - g[i + 1][m - 1]
		elif g[i][m - 1] == 1:
			o += 1
			op.append([i, m - 1, i + 1, m - 2, i + 1, m - 1])
			g[i + 1][m - 2] = 1 - g[i + 1][m - 2]
			g[i + 1][m - 1] = 1 - g[i + 1][m - 1]
	for j in range(m - 2):
		if g[n - 2][j] == 1:
			o += 1
			if g[n - 1][j] == 1:
				op.append([n - 2, j, n - 1, j, n - 2, j + 1])
				g[n - 2][j + 1] = 1 - g[n - 2][j + 1]
			else:
				op.append([n - 2, j, n - 1, j + 1, n - 2, j + 1])
				g[n - 2][j + 1] = 1 - g[n - 2][j + 1]
				g[n - 1][j + 1] = 1 - g[n - 1][j + 1]
		elif g[n - 1][j] == 1:
			o += 1
			op.append([n - 1, j, n - 2, j + 1, n - 1, j + 1])
			g[n - 2][j + 1] = 1 - g[n - 2][j + 1]
			g[n - 1][j + 1] = 1 - g[n - 1][j + 1]
	d = {0: [], 1: []}
	for i in range(n - 2, n):
		for j in range(m - 2, m):
			d[g[i][j]].append([i, j])
	if len(d[1]) == 4:
		o += 4
		op.append([n - 2, m - 2, n - 1, m - 2, n - 2, m - 1])
		op.append([n - 1, m - 1, n - 2, m - 2, n - 1, m - 2])
		op.append([n - 2, m - 1, n - 1, m - 1, n - 2, m - 2])
		op.append([n - 1, m - 2, n - 2, m - 1, n - 1, m - 1])
	elif len(d[1]) == 3:
		o += 1
		oper = []
		l = d[1]
		for (x, y) in l:
			oper.append(x)
			oper.append(y)
		op.append(oper)
	elif len(d[1]) == 2:
		o += 2
		oper = []
		l = d[0]
		for (x, y) in l:
			oper.append(x)
			oper.append(y)
		oper.append(d[1][0][0])
		oper.append(d[1][0][1])
		op.append(oper)
		oper = []
		for (x, y) in l:
			oper.append(x)
			oper.append(y)
		oper.append(d[1][1][0])
		oper.append(d[1][1][1])
		op.append(oper)
	elif len(d[1]) == 1:
		o += 3
		oper = []
		oper.append(d[1][0][0])
		oper.append(d[1][0][1])
		oper.append(d[0][0][0])
		oper.append(d[0][0][1])
		oper.append(d[0][1][0])
		oper.append(d[0][1][1])
		op.append(oper)
		newd = {0: [d[1][0], d[0][2]], 1: [d[0][0], d[0][1]]}
		d = newd
		oper = []
		l = d[0]
		for (x, y) in l:
			oper.append(x)
			oper.append(y)
		oper.append(d[1][0][0])
		oper.append(d[1][0][1])
		op.append(oper)
		oper = []
		for (x, y) in l:
			oper.append(x)
			oper.append(y)
		oper.append(d[1][1][0])
		oper.append(d[1][1][1])
		op.append(oper)
	print(o)
	for i in range(o):
		k = [x + 1 for x in op[i]]
		print(' '.join(map(str, k)))


def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def fix2by2(x, y):
	cnt = 0
	for i in range(x, x + 2):
		for j in range(y, y + 2):
			if arr[i][j] == 1:
				cnt += 1
	if cnt == 0:
		return []
	if cnt == 1:
		return fixOne(x, y)
	if cnt == 2:
		return fixTwo(x, y)
	if cnt == 3:
		return fixThree(x, y)
	if cnt == 4:
		return fixFour(x, y)

def getOneTwoThreeFour(x, y):
	blx = x + 1
	bly = y + 1
	one = [blx + 1, bly, blx, bly, blx, bly + 1]
	two = [blx, bly, blx, bly + 1, blx + 1, bly + 1]
	three = [blx, bly + 1, blx + 1, bly + 1, blx + 1, bly]
	four = [blx, bly, blx + 1, bly, blx + 1, bly + 1]
	return [one, two, three, four]

def fixOne(x, y):
	(one, two, three, four) = getOneTwoThreeFour(x, y)
	if arr[x][y] == 1:
		return [one, two, four]
	if arr[x + 1][y] == 1:
		return [one, three, four]
	if arr[x + 1][y + 1] == 1:
		return [two, three, four]
	if arr[x][y + 1] == 1:
		return [one, two, three]

def fixTwo(x, y):
	(one, two, three, four) = getOneTwoThreeFour(x, y)
	if arr[x][y] == arr[x][y + 1] == 1:
		return [three, four]
	if arr[x][y] == arr[x + 1][y] == 1:
		return [two, three]
	if arr[x][y] == arr[x + 1][y + 1] == 1:
		return [one, three]
	if arr[x + 1][y] == arr[x + 1][y + 1] == 1:
		return [one, two]
	if arr[x][y + 1] == arr[x + 1][y + 1] == 1:
		return [one, four]
	if arr[x + 1][y] == arr[x][y + 1] == 1:
		return [two, four]

def fixThree(x, y):
	(one, two, three, four) = getOneTwoThreeFour(x, y)
	if arr[x][y] == 0:
		return [three]
	if arr[x + 1][y] == 0:
		return [two]
	if arr[x][y + 1] == 0:
		return [four]
	if arr[x + 1][y + 1] == 0:
		return [one]

def fixFour(x, y):
	(one, two, three, four) = getOneTwoThreeFour(x, y)
	return [one, two, three, four]
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')
t = int(input())
for _ in range(t):
	(n, m) = [int(x) for x in input().split()]
	arr = []
	for _ in range(n):
		arr.append([int(x) for x in list(input())])
	ans = []
	starti = 0 if n % 2 == 0 else 1
	startj = 0 if m % 2 == 0 else 1
	if n % 2 == 1 and m % 2 == 1:
		starti = 1
		startj = 1
		if arr[0][0] == 1:
			ans.append([1, 1, 1, 2, 2, 1])
			arr[0][0] = 0
			arr[0][1] = 1 - arr[0][1]
			arr[1][0] = 1 - arr[1][0]
	if n % 2 == 1:
		i = 0
		for j in range(startj, m):
			if arr[i][j] == 1:
				if j == 0:
					ans.append([i + 1, j + 1, i + 2, j + 1, i + 2, j + 2])
					arr[i][j] = 0
					arr[i + 1][j] = 1 - arr[i + 1][j]
					arr[i + 1][j + 1] = 1 - arr[i + 1][j + 1]
				else:
					ans.append([i + 1, j + 1, i + 2, j, i + 2, j + 1])
					arr[i][j] = 0
					arr[i + 1][j] = 1 - arr[i + 1][j]
					arr[i + 1][j - 1] = 1 - arr[i + 1][j - 1]
	if m % 2 == 1:
		j = 0
		for i in range(starti, n):
			if arr[i][j] == 1:
				if i != n - 1:
					ans.append([i + 1, j + 1, i + 1, j + 2, i + 2, j + 2])
					arr[i][j] = 0
					arr[i][j + 1] = 1 - arr[i][j + 1]
					arr[i + 1][j + 1] = 1 - arr[i + 1][j + 1]
				else:
					ans.append([i + 1, j + 1, i + 1, j + 2, i, j + 2])
					arr[i][j] = 0
					arr[i][j + 1] = 1 - arr[i][j + 1]
					arr[i - 1][j + 1] = 1 - arr[i - 1][j + 1]
	for i in range(starti, n, 2):
		for j in range(startj, m, 2):
			for res in fix2by2(i, j):
				ans.append(res)
	print(len(ans))
	multiLineArrayOfArraysPrint(ans)


def aze(w):
	(x, y) = (w[0], w[1])
	s[x - 1][y - 1] ^= 1
	(x, y) = (w[2], w[3])
	s[x - 1][y - 1] ^= 1
	(x, y) = (w[4], w[5])
	s[x - 1][y - 1] ^= 1
for _ in range(int(input())):
	(n, m) = map(int, input().split())
	s = [[] for i in range(n)]
	for i in range(n):
		s[i] = [int(j) for j in str(input())]
	an = []
	for i in range(n - 2):
		for j in range(m - 1):
			if s[i][j]:
				(x, y) = (i + 1, j + 1)
				an.append([x, y, x + 1, y, x + 1, y + 1])
				aze([x, y, x + 1, y, x + 1, y + 1])
		j = m - 1
		if s[i][-1]:
			(x, y) = (i + 1, j + 1)
			an.append([x, y, x + 1, y - 1, x + 1, y])
			aze([x, y, x + 1, y - 1, x + 1, y])
	i = n - 2
	for j in range(m - 2):
		(x, y) = (i + 1, j + 1)
		if s[i][j] and s[i + 1][j]:
			an.append([x, y, x + 1, y, x, y + 1])
			aze([x, y, x + 1, y, x, y + 1])
		elif s[i][j]:
			an.append([x, y, x, y + 1, x + 1, y + 1])
			aze([x, y, x, y + 1, x + 1, y + 1])
		elif s[i + 1][j]:
			an.append([x + 1, y, x, y + 1, x + 1, y + 1])
			aze([x + 1, y, x, y + 1, x + 1, y + 1])
	one = []
	zer = []
	(i, j) = (n - 2, m - 2)
	(x, y) = (i + 1, j + 1)
	if s[i][j]:
		one.append([x, y])
	else:
		zer.append([x, y])
	if s[i][j + 1]:
		one.append([x, y + 1])
	else:
		zer.append([x, y + 1])
	if s[i + 1][j]:
		one.append([x + 1, y])
	else:
		zer.append([x + 1, y])
	if s[i + 1][j + 1]:
		one.append([x + 1, y + 1])
	else:
		zer.append([x + 1, y + 1])
	if len(one) == 3:
		an.append(one[0] + one[1] + one[2])
		aze(one[0] + one[1] + one[2])
	elif len(one) == 2:
		an.append(one[0] + zer[0] + zer[1])
		aze(one[0] + zer[0] + zer[1])
		an.append(one[1] + zer[0] + zer[1])
		aze(one[1] + zer[0] + zer[1])
	elif len(one) == 1:
		an.append(one[0] + zer[0] + zer[1])
		aze(one[0] + zer[0] + zer[1])
		an.append(one[0] + zer[0] + zer[2])
		aze(one[0] + zer[0] + zer[2])
		an.append(one[0] + zer[1] + zer[2])
		aze(one[0] + zer[1] + zer[2])
	elif len(one) == 4:
		an.append(one[0] + one[1] + one[2])
		aze(one[0] + one[1] + one[2])
		an.append(one[3] + one[0] + one[1])
		aze(one[3] + one[0] + one[1])
		an.append(one[1] + one[2] + one[3])
		aze(one[1] + one[2] + one[3])
		an.append(one[0] + one[2] + one[3])
		aze(one[0] + one[2] + one[3])
	print(len(an))
	for i in an:
		print(*i)


import math
inf = float('inf')
mod = 10 ** 9 + 7
for _ in range(int(input())):
	(m, n) = map(int, input().split())
	A = [[0] * (n + 1)] + [[0] + list(map(int, list(input()))) for _ in range(m)]
	ans = []
	for i in range(1, m - 1):
		for j in range(1, n + 1):
			if A[i][j]:
				ans.append([i, j, i + 1, j, i + 1, j + 1 if j < n else j - 1])
				A[i][j] ^= 1
				A[i + 1][j] ^= 1
				A[i + 1][j + 1 if j < n else j - 1] ^= 1
	for j in range(1, n - 1):
		if A[m - 1][j] and A[m][j]:
			ans.append([m - 1, j, m, j, m - 1, j + 1])
			A[m - 1][j] ^= 1
			A[m][j] ^= 1
			A[m - 1][j + 1] ^= 1
		elif A[m - 1][j]:
			ans.append([m - 1, j, m - 1, j + 1, m, j + 1])
			A[m - 1][j] ^= 1
			A[m - 1][j + 1] ^= 1
			A[m][j + 1] ^= 1
		elif A[m][j]:
			ans.append([m, j, m, j + 1, m - 1, j + 1])
			A[m][j] ^= 1
			A[m][j + 1] ^= 1
			A[m - 1][j + 1] ^= 1
	if A[m - 1][n - 1] ^ A[m - 1][n] ^ A[m][n - 1]:
		ans.append([m - 1, n - 1, m - 1, n, m, n - 1])
	if A[m - 1][n - 1] ^ A[m][n - 1] ^ A[m][n]:
		ans.append([m - 1, n - 1, m, n - 1, m, n])
	if A[m][n - 1] ^ A[m][n] ^ A[m - 1][n]:
		ans.append([m, n - 1, m, n, m - 1, n])
	if A[m][n] ^ A[m - 1][n] ^ A[m - 1][n - 1]:
		ans.append([m, n, m - 1, n, m - 1, n - 1])
	print(len(ans))
	for a in ans:
		print(*a)


d = {'0': 0, '1': 1}
cases = int(input())
for t in range(cases):
	(n, m) = list(map(int, input().split()))
	matrix = []
	for i in range(n):
		matrix.append([d[i] for i in input()])
	k = 0
	out = []
	for i in range(n - 2):
		for j in range(m):
			if matrix[i][j]:
				k += 1
				if j < m - 1:
					matrix[i][j] = 0
					matrix[i + 1][j] = matrix[i + 1][j] ^ 1
					matrix[i + 1][j + 1] = matrix[i + 1][j + 1] ^ 1
					out.append([i, j, i + 1, j, i + 1, j + 1])
				elif j == m - 1:
					matrix[i][j] = 0
					matrix[i + 1][j] = matrix[i + 1][j] ^ 1
					matrix[i + 1][j - 1] = matrix[i + 1][j - 1] ^ 1
					out.append([i, j, i + 1, j, i + 1, j - 1])
	for i in range(m - 1):
		(x1, x2) = (matrix[n - 2][i], matrix[n - 1][i])
		if x1 == 0 and x2 == 0:
			continue
		elif x1 == 1 and x2 == 1:
			out.append([n - 2, i, n - 1, i, n - 1, i + 1])
			matrix[n - 2][i] ^= 1
			matrix[n - 1][i] ^= 1
			matrix[n - 1][i + 1] ^= 1
		elif x1 == 0 and x2 == 1:
			out.append([n - 2, i + 1, n - 1, i, n - 1, i + 1])
			matrix[n - 2][i + 1] ^= 1
			matrix[n - 1][i] ^= 1
			matrix[n - 1][i + 1] ^= 1
		elif x1 == 1 and x2 == 0:
			out.append([n - 2, i, n - 2, i + 1, n - 1, i + 1])
			matrix[n - 2][i] ^= 1
			matrix[n - 2][i + 1] ^= 1
			matrix[n - 1][i + 1] ^= 1
		k += 1
	if matrix[-1][-1] or matrix[-2][-1]:
		(x1, x2, x3, x4) = (matrix[n - 2][m - 2], matrix[n - 2][m - 1], matrix[n - 1][m - 2], matrix[n - 1][m - 1])
		if x2 == 1 and x4 == 1:
			out.append([n - 2, m - 2, n - 2, m - 1, n - 1, m - 2])
			out.append([n - 2, m - 2, n - 1, m - 2, n - 1, m - 1])
			(matrix[n - 2][m - 1], matrix[n - 1][m - 1]) = (0, 0)
			k += 2
		elif x2 == 0 and x4 == 1:
			out.append([n - 2, m - 2, n - 1, m - 2, n - 1, m - 1])
			out.append([n - 2, m - 2, n - 2, m - 1, n - 1, m - 1])
			out.append([n - 2, m - 1, n - 1, m - 2, n - 1, m - 1])
			matrix[n - 1][m - 1] = 0
			k += 3
		elif x2 == 1 and x4 == 0:
			out.append([n - 2, m - 2, n - 2, m - 1, n - 1, m - 2])
			out.append([n - 2, m - 2, n - 2, m - 1, n - 1, m - 1])
			out.append([n - 2, m - 1, n - 1, m - 2, n - 1, m - 1])
			matrix[n - 2][m - 1] = 0
			k += 3
	print(k)
	for (x1, y1, x2, y2, x3, y3) in out:
		print(x1 + 1, y1 + 1, x2 + 1, y2 + 1, x3 + 1, y3 + 1)


mod = 10 ** 9 + 7

def count(v):
	ret = 0
	for x in v:
		for val in x:
			if val == 1:
				ret += 1
	return ret

def check(v):
	cnt = count(v)
	v1 = []
	v0 = []
	for i in range(2):
		for j in range(2):
			if v[i][j] == 1:
				v1.append([i, j])
			else:
				v0.append([i, j])
	if cnt == 1:
		return v1 + v0[:2]
	elif cnt == 2:
		return v1[:1] + v0
	elif cnt == 3:
		return v1
	else:
		return v1[:3]

def solve():
	(n, m) = map(int, input().split())
	s = []
	for i in range(n):
		t = list(input())
		v = []
		for j in range(m):
			v.append(int(t[j]))
		s.append(v)
	ans = []
	for i in range(n - 2):
		for j in range(m - 2):
			if s[i][j] == 1:
				ans.append([i, j, i, j + 1, i + 1, j])
				s[i][j] = 1 - s[i][j]
				s[i][j + 1] = 1 - s[i][j + 1]
				s[i + 1][j] = 1 - s[i + 1][j]
	for i in range(n - 2):
		if s[i][m - 2] == 1 and s[i][m - 1] == 1:
			s[i][m - 2] = 0
			s[i][m - 1] = 0
			s[i + 1][m - 2] = 1 - s[i + 1][m - 2]
			ans.append([i, m - 2, i, m - 1, i + 1, m - 2])
		elif s[i][m - 2] == 1:
			s[i][m - 2] = 0
			s[i + 1][m - 2] = 1 - s[i + 1][m - 2]
			s[i + 1][m - 1] = 1 - s[i + 1][m - 1]
			ans.append([i, m - 2, i + 1, m - 2, i + 1, m - 1])
		elif s[i][m - 1] == 1:
			s[i][m - 1] = 0
			s[i + 1][m - 2] = 1 - s[i + 1][m - 2]
			s[i + 1][m - 1] = 1 - s[i + 1][m - 1]
			ans.append([i, m - 1, i + 1, m - 2, i + 1, m - 1])
	for j in range(m - 2):
		if s[n - 2][j] == 1 and s[n - 1][j] == 1:
			s[n - 2][j] = 0
			s[n - 1][j] = 0
			s[n - 2][j + 1] = 1 - s[n - 2][j + 1]
			ans.append([n - 2, j, n - 1, j, n - 2, j + 1])
		elif s[n - 2][j] == 1:
			s[n - 2][j] = 0
			s[n - 2][j + 1] = 1 - s[n - 2][j + 1]
			s[n - 1][j + 1] = 1 - s[n - 1][j + 1]
			ans.append([n - 2, j, n - 2, j + 1, n - 1, j + 1])
		elif s[n - 1][j] == 1:
			s[n - 1][j] = 0
			s[n - 2][j + 1] = 1 - s[n - 2][j + 1]
			s[n - 1][j + 1] = 1 - s[n - 1][j + 1]
			ans.append([n - 1, j, n - 2, j + 1, n - 1, j + 1])
	while s[n - 1][m - 1] + s[n - 1][m - 2] + s[n - 2][m - 1] + s[n - 2][m - 2] > 0:
		v = check([[s[n - 2][m - 2], s[n - 2][m - 1]], [s[n - 1][m - 2], s[n - 1][m - 1]]])
		for i in range(3):
			s[n - 2 + v[i][0]][m - 2 + v[i][1]] = 1 - s[n - 2 + v[i][0]][m - 2 + v[i][1]]
		ans.append([n - 2 + v[0][0], m - 2 + v[0][1], n - 2 + v[1][0], m - 2 + v[1][1], n - 2 + v[2][0], m - 2 + v[2][1]])
	print(len(ans))
	for x in ans:
		for val in x:
			print(val + 1, end=' ')
		print()
t = 1
t = int(input())
while t > 0:
	solve()
	t -= 1


import io
import os

def solve():
	(n, m) = map(int, input().split())
	vals = []
	for _ in range(n):
		vals.append(list(map(int, input())))
	ops = []

	def flip(x1, y1, x2, y2, x3, y3):
		for (a, b) in ([x1, y1], [x2, y2], [x3, y3]):
			vals[b][a] = 1 - vals[b][a]
		ops.append((y1 + 1, x1 + 1, y2 + 1, x2 + 1, y3 + 1, x3 + 1))
	for y in range(n - 2):
		for x in range(m):
			if x == m - 1:
				if vals[y][x]:
					flip(x, y, x, y + 1, x - 1, y + 1)
			elif vals[y][x]:
				flip(x, y, x, y + 1, x + 1, y + 1)
	for x in range(m - 2):
		if vals[n - 2][x]:
			flip(x, n - 2, x + 1, n - 2, x + 1, n - 1)
		if vals[n - 1][x]:
			flip(x, n - 1, x + 1, n - 2, x + 1, n - 1)
	a = (m - 2, n - 2)
	b = (m - 1, n - 2)
	c = (m - 2, n - 1)
	d = (m - 1, n - 1)

	def last():
		return [vals[y][x] for (x, y) in [a, b, c, d]]
	if sum(last()) == 4:
		flip(*a, *b, *c)
	if sum(last()) == 1:
		i = last().index(1)
		if i == 0:
			flip(*a, *b, *c)
		elif i == 1:
			flip(*b, *d, *c)
		elif i == 2:
			flip(*a, *c, *d)
		else:
			flip(*b, *d, *c)
	if sum(last()) == 2:
		if last() == [1, 1, 0, 0]:
			flip(*a, *c, *d)
		elif last() == [1, 0, 1, 0]:
			flip(*a, *b, *d)
		elif last() == [1, 0, 0, 1]:
			flip(*a, *b, *c)
		elif last() == [0, 1, 1, 0]:
			flip(*a, *b, *d)
		elif last() == [0, 1, 0, 1]:
			flip(*a, *b, *c)
		else:
			flip(*a, *b, *c)
	if sum(last()) == 3:
		i = last().index(0)
		if i == 0:
			flip(*b, *c, *d)
		elif i == 1:
			flip(*a, *c, *d)
		elif i == 2:
			flip(*a, *b, *d)
		else:
			flip(*a, *b, *c)
	for row in vals:
		assert not any(row)
	print(len(ops))
	for op in ops:
		print(*op)
t = int(input())
for _ in range(t):
	solve()


import sys
from array import array
import typing as Tp

def input():
	return sys.stdin.buffer.readline().decode('utf-8')

def output(*args):
	sys.stdout.buffer.write(('\n'.join(map(str, args)) + '\n').encode('utf-8'))

def hoge(mat, i1, j1, i2, j2, i3, j3):
	mat[i1][j1] ^= 1
	mat[i2][j2] ^= 1
	mat[i3][j3] ^= 1
	return f'{i1 + 1} {j1 + 1} {i2 + 1} {j2 + 1} {i3 + 1} {j3 + 1}'

def solve(mat, i, j, flag=0):
	res = []
	while True:
		zero = [(k, l) for k in (i, i + 1) for l in (j, j + 1) if mat[k][l] == 0]
		one = [(k, l) for k in (i, i + 1) for l in (j, j + 1) if mat[k][l] == 1]
		if not one or (flag == 0 and mat[i][j] == 0) or (flag == 1 and mat[i][j] == mat[i][j + 1] == 0) or (flag == 2 and mat[i][j] == mat[i + 1][j] == 0):
			break
		elif len(one) == 3:
			res.append(hoge(mat, one[0][0], one[0][1], one[1][0], one[1][1], one[2][0], one[2][1]))
		elif len(one) == 4:
			res.append(hoge(mat, i, j, i + 1, j, i, j + 1))
		elif len(one) == 1:
			if one[0][0] == i:
				res.append(hoge(mat, one[0][0], one[0][1], i + 1, j, i + 1, j + 1))
			else:
				res.append(hoge(mat, one[0][0], one[0][1], zero[0][0], zero[0][1], zero[1][0], zero[1][1]))
		elif len(one) == 2:
			res.append(hoge(mat, one[0][0], one[0][1], zero[0][0], zero[0][1], zero[1][0], zero[1][1]))
	return res

def main():
	t = int(input())
	ans_a = [''] * t
	for ti in range(t):
		(n, m) = map(int, input().split())
		ans = []
		matrix = [list(map(int, input().rstrip())) for _ in range(n)]
		for i in list(range(0, n - 1)):
			for j in range(0, m - 1):
				ans.extend(solve(matrix, i, j, (2 if i == n - 2 else 0) + (1 if j == m - 2 else 0)))
		assert all((sum(row) == 0 for row in matrix))
		if len(ans) > n * m:
			while True:
				...
		ans_a[ti] = f'{len(ans)}' + ('\n' + '\n'.join(ans) if ans else '')
	output(*ans_a)
main()


def f(c):
	if c == '1':
		return '0'
	return '1'
for _ in range(int(input())):
	(n, m) = map(int, input().split())
	arr = [list(input()) for i in range(n)]

	def do(x):
		res.append(x)
		arr[x[0] - 1][x[1] - 1] = f(arr[x[0] - 1][x[1] - 1])
		arr[x[2] - 1][x[3] - 1] = f(arr[x[2] - 1][x[3] - 1])
		arr[x[4] - 1][x[5] - 1] = f(arr[x[4] - 1][x[5] - 1])
	res = []
	if n % 2 == 1:
		for j in range(m - 1):
			if arr[n - 1][j] == '0':
				continue
			do((n, j + 1, n - 1, j + 1, n - 1, j + 2))
		if arr[n - 1][m - 1] == '1':
			do((n, m, n - 1, m, n - 1, m - 1))
		n -= 1
	if m % 2 == 1:
		for i in range(n - 1):
			if arr[i][m - 1] == '0':
				continue
			do((i + 1, m, i + 1, m - 1, i + 2, m - 1))
		if arr[n - 1][m - 1] == '1':
			do((n, m, n, m - 1, n - 1, m - 1))
		m -= 1
	for i in range(0, n, 2):
		for j in range(0, m, 2):
			a = [arr[i][j], arr[i + 1][j], arr[i][j + 1], arr[i + 1][j + 1]]
			if a.count('0') == 4:
				continue
			if a.count('1') == 4:
				do((i + 1, j + 1, i + 2, j + 1, i + 1, j + 2))
				do((i + 2, j + 2, i + 2, j + 1, i + 1, j + 2))
				do((i + 1, j + 1, i + 2, j + 2, i + 1, j + 2))
				do((i + 1, j + 1, i + 2, j + 1, i + 2, j + 2))
				continue
			if a.count('1') == 2:
				do((i + 1, j + 1, i + 2, j + 1, i + 1, j + 2))
				a = [arr[i][j], arr[i + 1][j], arr[i][j + 1], arr[i + 1][j + 1]]
			if a.count('1') == 3:
				if arr[i][j] == '0':
					do((i + 1, j + 2, i + 2, j + 1, i + 2, j + 2))
				elif arr[i + 1][j] == '0':
					do((i + 1, j + 2, i + 1, j + 1, i + 2, j + 2))
				elif arr[i][j + 1] == '0':
					do((i + 1, j + 1, i + 2, j + 1, i + 2, j + 2))
				elif arr[i + 1][j + 1] == '0':
					do((i + 1, j + 2, i + 2, j + 1, i + 1, j + 1))
			if a.count('1') == 1:
				if arr[i][j] == '1':
					do((i + 1, j + 2, i + 2, j + 1, i + 1, j + 1))
					do((i + 1, j + 2, i + 1, j + 1, i + 2, j + 2))
					do((i + 1, j + 1, i + 2, j + 1, i + 2, j + 2))
				elif arr[i + 1][j + 1] == '1':
					do((i + 1, j + 2, i + 2, j + 1, i + 2, j + 2))
					do((i + 1, j + 2, i + 1, j + 1, i + 2, j + 2))
					do((i + 1, j + 1, i + 2, j + 1, i + 2, j + 2))
				elif arr[i + 1][j] == '1':
					do((i + 1, j + 1, i + 2, j + 1, i + 2, j + 2))
					do((i + 1, j + 2, i + 2, j + 1, i + 2, j + 2))
					do((i + 1, j + 2, i + 2, j + 1, i + 1, j + 1))
				elif arr[i][j + 1] == '1':
					do((i + 1, j + 2, i + 1, j + 1, i + 2, j + 2))
					do((i + 1, j + 2, i + 2, j + 1, i + 2, j + 2))
					do((i + 1, j + 2, i + 2, j + 1, i + 1, j + 1))
	print(len(res))
	for e in res:
		print(*e)


from copy import deepcopy

def get_moves(matrix_orig, n, m, down, forward):
	matrix = deepcopy(matrix_orig)
	moves = []
	if down:
		delta_i = 1
		i_range = range(n - 1)
		last_i = n - 1
	else:
		delta_i = -1
		i_range = range(n - 1, 0, -1)
		last_i = 0
	if forward:
		delta_j = 1
		j_range = range(m - 1)
		last_j = m - 1
	else:
		delta_j = -1
		j_range = range(m - 1, 0, -1)
		last_j = 0
	for i in i_range:
		for j in j_range:
			if matrix[i][j] == 1 and matrix[i + delta_i][j] == 0:
				matrix[i][j] = 0
				matrix[i][j + delta_j] ^= 1
				matrix[i + delta_i][j + delta_j] ^= 1
				moves.append((i, j, i, j + delta_j, i + delta_i, j + delta_j))
			elif matrix[i][j] == 1 and matrix[i + delta_i][j] == 1 and (matrix[i + delta_i][j + delta_j] == 1):
				matrix[i][j] = 0
				matrix[i + delta_i][j] ^= 1
				matrix[i + delta_i][j + delta_j] ^= 1
				moves.append((i, j, i + delta_i, j, i + delta_i, j + delta_j))
			elif matrix[i][j] == 1:
				matrix[i][j] = 0
				matrix[i + delta_i][j] ^= 1
				matrix[i][j + delta_j] ^= 1
				moves.append((i, j, i + delta_i, j, i, j + delta_j))
		j = last_j
		if matrix[i][j] == 1:
			matrix[i][j] = 0
			matrix[i + delta_i][j] ^= 1
			matrix[i + delta_i][j - delta_j] ^= 1
			moves.append((i, j, i + delta_i, j, i + delta_i, j - delta_j))
	i = last_i
	for j in j_range:
		if matrix[i][j] == 1 and matrix[i][j + delta_j] == 1:
			matrix[i][j] = 0
			matrix[i][j + delta_j] = 0
			moves.append((i, j, i - delta_i, j, i - delta_i, j + delta_j))
			moves.append((i, j + delta_j, i - delta_i, j, i - delta_i, j + delta_j))
		elif matrix[i][j] == 1:
			matrix[i][j] = 0
			moves.append((i, j, i - delta_i, j, i - delta_i, j + delta_j))
			moves.append((i, j, i, j + delta_j, i - delta_i, j + delta_j))
			moves.append((i, j, i - delta_i, j, i, j + delta_j))
	j = last_j
	if matrix[i][j] == 1:
		matrix[i][j] = 0
		moves.append((i, j, i - delta_i, j, i - delta_i, j - delta_j))
		moves.append((i, j, i, j - delta_j, i - delta_i, j - delta_j))
		moves.append((i, j, i - delta_i, j, i, j - delta_j))
	return moves
t = int(input())
for _ in range(t):
	(n, m) = map(int, input().split())
	matrix = []
	for _ in range(n):
		matrix.append([int(i) for i in input()])
	moves_1 = get_moves(matrix, n, m, True, True)
	moves_2 = get_moves(matrix, n, m, True, False)
	moves_3 = get_moves(matrix, n, m, False, True)
	moves_4 = get_moves(matrix, n, m, False, False)
	moves = moves_1
	for mvs in [moves_2, moves_3, moves_4]:
		if len(mvs) < len(moves):
			moves = mvs
	print(len(moves))
	for move in moves:
		print(' '.join([str(i + 1) for i in move]))


global mat

def calc(a, b, c, d, e, f):
	mat[a - 1][b - 1] = str(int(mat[a - 1][b - 1]) ^ 1)
	mat[c - 1][d - 1] = str(int(mat[c - 1][d - 1]) ^ 1)
	mat[e - 1][f - 1] = str(int(mat[e - 1][f - 1]) ^ 1)
for _ in range(int(input())):
	(n, m) = map(int, input().split())
	mat = []
	k = 0
	ans = []
	for i in range(n):
		mat.append(list(input()))
	for i in range(1, n):
		for j in range(1, m):
			if i == n - 1 and j == m - 1:
				temp = int(mat[i - 1][j - 1]) + int(mat[i][j - 1]) + int(mat[i - 1][j]) + int(mat[i][j])
				tlist = [[i - 1, j - 1], [i, j - 1], [i - 1, j], [i, j]]
				if temp != 0:
					if temp == 4:
						k += 1
						ans.append([i, j, i + 1, j, i, j + 1])
						calc(i, j, i + 1, j, i, j + 1)
						temp = 1
					if temp == 1:
						k += 1
						tans = []
						zc = 0
						for x in tlist:
							if mat[x[0]][x[1]] == '1':
								tans.append(x[0] + 1)
								tans.append(x[1] + 1)
							elif zc < 2:
								tans.append(x[0] + 1)
								tans.append(x[1] + 1)
								zc += 1
						ans.append(tans)
						calc(tans[0], tans[1], tans[2], tans[3], tans[4], tans[5])
						temp = 2
					if temp == 2:
						k += 1
						tans = []
						zo = 0
						for x in tlist:
							if mat[x[0]][x[1]] == '1' and zo < 1:
								tans.append(x[0] + 1)
								tans.append(x[1] + 1)
								zo += 1
							elif mat[x[0]][x[1]] == '0':
								tans.append(x[0] + 1)
								tans.append(x[1] + 1)
						ans.append(tans)
						calc(tans[0], tans[1], tans[2], tans[3], tans[4], tans[5])
						temp = 3
					if temp == 3:
						k += 1
						tans = []
						for x in tlist:
							if mat[x[0]][x[1]] == '1':
								tans.append(x[0] + 1)
								tans.append(x[1] + 1)
						ans.append(tans)
						calc(tans[0], tans[1], tans[2], tans[3], tans[4], tans[5])
			elif i == n - 1:
				if mat[i - 1][j - 1] == '1' and mat[i][j - 1] == '1':
					k += 1
					ans.append([i, j, i + 1, j, i, j + 1])
					calc(i, j, i + 1, j, i, j + 1)
				elif mat[i - 1][j - 1] == '1' and mat[i][j - 1] == '0':
					k += 1
					ans.append([i, j, i, j + 1, i + 1, j + 1])
					calc(i, j, i, j + 1, i + 1, j + 1)
				elif mat[i - 1][j - 1] == '0' and mat[i][j - 1] == '1':
					k += 1
					ans.append([i + 1, j, i, j + 1, i + 1, j + 1])
					calc(i + 1, j, i, j + 1, i + 1, j + 1)
			elif j == m - 1:
				if mat[i - 1][j - 1] == '1' and mat[i - 1][j] == '1':
					k += 1
					ans.append([i, j, i, j + 1, i + 1, j])
					calc(i, j, i, j + 1, i + 1, j)
				elif mat[i - 1][j - 1] == '1' and mat[i - 1][j] == '0':
					k += 1
					ans.append([i, j, i + 1, j, i + 1, j + 1])
					calc(i, j, i + 1, j, i + 1, j + 1)
				elif mat[i - 1][j - 1] == '0' and mat[i - 1][j] == '1':
					k += 1
					ans.append([i, j + 1, i + 1, j, i + 1, j + 1])
					calc(i, j + 1, i + 1, j, i + 1, j + 1)
			elif mat[i - 1][j - 1] == '1':
				k += 1
				ans.append([i, j, i, j + 1, i + 1, j])
				calc(i, j, i, j + 1, i + 1, j)
	print(k)
	for i in ans:
		for j in i:
			print(j, end=' ')
		print()


for _ in range(int(input())):
	(m, n) = map(int, input().split())
	A = [[0] * (n + 1)] + [[0] + list(map(int, list(input()))) for _ in range(m)]
	ans = []
	for i in range(1, m - 1):
		for j in range(1, n + 1):
			if A[i][j]:
				ans.append([i, j, i + 1, j, i + 1, j + 1 if j < n else j - 1])
				A[i][j] ^= 1
				A[i + 1][j] ^= 1
				A[i + 1][j + 1 if j < n else j - 1] ^= 1
	for j in range(1, n - 1):
		if A[m - 1][j] and A[m][j]:
			ans.append([m - 1, j, m, j, m - 1, j + 1])
			A[m - 1][j] ^= 1
			A[m][j] ^= 1
			A[m - 1][j + 1] ^= 1
		elif A[m - 1][j]:
			ans.append([m - 1, j, m - 1, j + 1, m, j + 1])
			A[m - 1][j] ^= 1
			A[m - 1][j + 1] ^= 1
			A[m][j + 1] ^= 1
		elif A[m][j]:
			ans.append([m, j, m, j + 1, m - 1, j + 1])
			A[m][j] ^= 1
			A[m][j + 1] ^= 1
			A[m - 1][j + 1] ^= 1
	if A[m - 1][n - 1] ^ A[m - 1][n] ^ A[m][n - 1]:
		ans.append([m - 1, n - 1, m - 1, n, m, n - 1])
	if A[m - 1][n - 1] ^ A[m][n - 1] ^ A[m][n]:
		ans.append([m - 1, n - 1, m, n - 1, m, n])
	if A[m][n - 1] ^ A[m][n] ^ A[m - 1][n]:
		ans.append([m, n - 1, m, n, m - 1, n])
	if A[m][n] ^ A[m - 1][n] ^ A[m - 1][n - 1]:
		ans.append([m, n, m - 1, n, m - 1, n - 1])
	print(len(ans))
	for a in ans:
		print(*a)


from os import path
import sys
from heapq import heappush, heappop
from functools import cmp_to_key as ctk
from collections import deque, Counter, defaultdict as dd
from bisect import bisect, bisect_left, bisect_right, insort, insort_left, insort_right
from itertools import permutations
from datetime import datetime
from math import ceil, sqrt, log, gcd

def ii():
	return int(input())

def si():
	return input().rstrip()

def mi():
	return map(int, input().split())

def li():
	return list(mi())
abc = 'abcdefghijklmnopqrstuvwxyz'
mod = 998244353
inf = float('inf')
vow = ['a', 'e', 'i', 'o', 'u']
(dx, dy) = ([-1, 1, 0, 0], [0, 0, 1, -1])

def bo(i):
	return ord(i) - ord('0')
file = 1

def solve():
	for _ in range(ii()):
		(n, m) = mi()
		a = []
		for i in range(n):
			s = si()
			p = []
			for j in s:
				p.append(int(j))
			a.append(p)

		def change(p):
			for i in range(0, 5, 2):
				a[p[i]][p[i + 1]] ^= 1
		ans = []
		for i in range(n - 2):
			for j in range(m):
				if a[i][j] == 0:
					if j == 0 or a[i][j - 1] == 0:
						continue
					else:
						ans.append([i, j - 1, i + 1, j - 1, i + 1, j])
						change(ans[-1])
				else:
					if j > 0 and a[i][j - 1] == 1:
						if a[i + 1][j - 1] == 1:
							ans.append([i, j, i + 1, j - 1, i, j - 1])
						else:
							ans.append([i, j, i, j - 1, i + 1, j])
					elif j < m - 1 and (a[i][j + 1] or a[i + 1][j + 1]):
						if a[i][j + 1] == 1:
							if a[i + 1][j] == 1:
								ans.append([i, j, i + 1, j, i, j + 1])
							else:
								ans.append([i, j, i + 1, j + 1, i, j + 1])
						else:
							ans.append([i, j, i + 1, j, i + 1, j + 1])
					elif j > 0:
						ans.append([i, j, i + 1, j - 1, i + 1, j])
					else:
						ans.append([i, j, i + 1, j + 1, i + 1, j])
					change(ans[-1])

		def count2(x1, y1, x2, y2):
			(o, z) = ([], [])
			for i in range(x1, x2 + 1):
				for j in range(y1, y2 + 1):
					if a[i][j]:
						o.append(i)
						o.append(j)
					else:
						z.append(i)
						z.append(j)
			p = []
			ans.append(z + o[:2])
			change(ans[-1])
			ans.append(z + o[2:])
			change(ans[-1])

		def count1(x1, y1, x2, y2):
			p = []
			cnt = 0
			for i in range(x1, x2 + 1):
				for j in range(y1, y2 + 1):
					if a[i][j]:
						p.append(i)
						p.append(j)
					elif cnt < 2:
						cnt += 1
						p.append(i)
						p.append(j)
			ans.append(p)
			change(ans[-1])
			count2(x1, y1, x2, y2)

		def func(x1, y1, x2, y2):
			cnt = 0
			for i in range(x1, x2 + 1):
				for j in range(y1, y2 + 1):
					cnt += a[i][j]
			if cnt == 0:
				return
			if cnt == 3:
				p = []
				for i in range(x1, x2 + 1):
					for j in range(y1, y2 + 1):
						if a[i][j]:
							p.append(i)
							p.append(j)
				ans.append(p)
				change(ans[-1])
			elif cnt == 2:
				count2(x1, y1, x2, y2)
			elif cnt == 1:
				count1(x1, y1, x2, y2)
			else:
				p = []
				for i in range(x1, x2 + 1):
					for j in range(y1, y2 + 1):
						if a[i][j]:
							p.append(i)
							p.append(j)
						if len(p) == 6:
							break
				ans.append(p)
				change(ans[-1])
				count1(x1, y1, x2, y2)
		if m & 1:
			if a[n - 2][m - 1] and a[n - 1][m - 1]:
				ans.append([n - 2, m - 1, n - 1, m - 1, n - 2, m - 2])
				change(ans[-1])
			elif a[n - 2][m - 1]:
				ans.append([n - 2, m - 1, n - 1, m - 2, n - 2, m - 2])
				change(ans[-1])
			elif a[n - 1][m - 1]:
				ans.append([n - 2, m - 2, n - 1, m - 1, n - 1, m - 2])
				change(ans[-1])
		for i in range(0, m - 1, 2):
			func(n - 2, i, n - 1, i + 1)
		print(len(ans))
		for i in ans:
			for j in i:
				print(j + 1, end=' ')
			print()
if file:
	if path.exists('input.txt'):
		sys.stdin = open('input.txt', 'r')
		sys.stdout = open('output.txt', 'w')
	else:
		input = sys.stdin.readline
solve()


import sys
input = sys.stdin.readline
a = None
ops = None

def update(loc):
	global a
	for i in range(len(loc) // 2):
		if a[loc[2 * i] - 1][loc[2 * i + 1] - 1] == '1':
			a[loc[2 * i] - 1][loc[2 * i + 1] - 1] = '0'
		else:
			a[loc[2 * i] - 1][loc[2 * i + 1] - 1] = '1'

def solve(i, j):
	global a
	global ops
	ones = []
	zeros = []
	for k in range(2):
		for l in range(2):
			if a[i + k][j + l] == '1':
				ones.append([i + k + 1, j + l + 1])
			else:
				zeros.append([i + k + 1, j + l + 1])
	if len(ones) == 4:
		op = []
		for k in range(3):
			update(ones[-1])
			op.extend(ones[-1])
			zeros.append(ones.pop())
		ops.append(op)
	if len(ones) > 0:
		while len(ones) != 3:
			op = []
			for k in range(2):
				update(zeros[-1])
				op.extend(zeros[-1])
				ones.append(zeros.pop())
			update(ones[-3])
			op.extend(ones[-3])
			zeros.append(ones[-3])
			del ones[-3]
			ops.append(op)
		op = []
		for k in range(3):
			update(ones[k])
			op.extend(ones[k])
		ops.append(op)

def prog():
	global a, ops
	for _ in range(int(input())):
		(n, m) = map(int, input().split())
		a = [list(input().strip()) for i in range(n)]
		ops = []
		if n % 2 == 1 and m % 2 == 0:
			for j in range(m - 1):
				if a[n - 1][j] == '1':
					ops.append([n - 1 + 1, j + 1, n - 2 + 1, j + 1, n - 2 + 1, j + 1 + 1])
					update([n - 1 + 1, j + 1, n - 2 + 1, j + 1, n - 2 + 1, j + 1 + 1])
			if a[n - 1][m - 1] == '1':
				ops.append([n - 1 + 1, m - 1 + 1, n - 2 + 1, m - 1 + 1, n - 2 + 1, m - 2 + 1])
				update([n - 1 + 1, m - 1 + 1, n - 2 + 1, m - 1 + 1, n - 2 + 1, m - 2 + 1])
		elif n % 2 == 0 and m % 2 == 1:
			for i in range(n - 1):
				if a[i][m - 1] == '1':
					ops.append([i + 1, m - 1 + 1, i + 1, m - 2 + 1, i + 1 + 1, m - 2 + 1])
					update([i + 1, m - 1 + 1, i + 1, m - 2 + 1, i + 1 + 1, m - 2 + 1])
			if a[n - 1][m - 1] == '1':
				ops.append([n - 1 + 1, m - 1 + 1, n - 1 + 1, m - 2 + 1, n - 2 + 1, m - 2 + 1])
				update([n - 1 + 1, m - 1 + 1, n - 1 + 1, m - 2 + 1, n - 2 + 1, m - 2 + 1])
		elif n % 2 == 1 and m % 2 == 1:
			if a[n - 1][m - 1] == '1':
				ops.append([n - 1 + 1, m - 1 + 1, n - 1 + 1, m - 2 + 1, n - 2 + 1, m - 2 + 1])
				update([n - 1 + 1, m - 1 + 1, n - 1 + 1, m - 2 + 1, n - 2 + 1, m - 2 + 1])
			for i in range(n - 2):
				if a[i][m - 1] == '1':
					ops.append([i + 1, m - 1 + 1, i + 1, m - 2 + 1, i + 1 + 1, m - 2 + 1])
					update([i + 1, m - 1 + 1, i + 1, m - 2 + 1, i + 1 + 1, m - 2 + 1])
			if a[n - 2][m - 1] == '1':
				ops.append([n - 2 + 1, m - 1 + 1, n - 2 + 1, m - 2 + 1, n - 3 + 1, m - 2 + 1])
				update([n - 2 + 1, m - 1 + 1, n - 2 + 1, m - 2 + 1, n - 3 + 1, m - 2 + 1])
			for j in range(m - 2):
				if a[n - 1][j] == '1':
					ops.append([n - 1 + 1, j + 1, n - 2 + 1, j + 1, n - 2 + 1, j + 1 + 1])
					update([n - 1 + 1, j + 1, n - 2 + 1, j + 1, n - 2 + 1, j + 1 + 1])
			if a[n - 1][m - 2] == '1':
				ops.append([n - 1 + 1, m - 2 + 1, n - 2 + 1, m - 2 + 1, n - 2 + 1, m - 3 + 1])
				update([n - 1 + 1, m - 2 + 1, n - 2 + 1, m - 2 + 1, n - 2 + 1, m - 3 + 1])
		for i in range(0, n - 1, 2):
			for j in range(0, m - 1, 2):
				solve(i, j)
		print(len(ops))
		for op in ops:
			print(*op)
prog()


for _ in range(int(input())):
	(n, m) = map(int, input().split())
	arr = [[*map(int, input())] for _ in range(n)]
	ans = []

	def invert(i, j, k, a, b, c):
		arr[i][j] = 1 if arr[i][j] == 0 else 0
		arr[k][a] = 1 if arr[k][a] == 0 else 0
		arr[b][c] = 1 if arr[b][c] == 0 else 0
	for i in range(n - 2):
		for j in range(m):
			if arr[i][j] == 1:
				ans.append([i, j, i + 1, j, i + 1, j + 1 if j == 0 else j - 1])
				invert(i, j, i + 1, j, i + 1, j + 1 if j == 0 else j - 1)
	i = n - 2
	for j in range(0, m, 2):
		if j == m - 1:
			j -= 1
		if arr[i][j] + arr[i + 1][j] + arr[i][j + 1] + arr[i + 1][j + 1] == 4:
			ans.append([i, j, i + 1, j, i, j + 1])
			invert(i, j, i + 1, j, i, j + 1)
			if j + 2 < m:
				ans.append([i + 1, j + 1, i + 1, j + 2, i, j + 2])
				invert(i + 1, j + 1, i + 1, j + 2, i, j + 2)
			else:
				ans.append([i, j, i, j + 1, i + 1, j + 1])
				invert(i, j, i, j + 1, i + 1, j + 1)
				ans.append([i, j, i + 1, j, i + 1, j + 1])
				invert(i, j, i + 1, j, i + 1, j + 1)
				ans.append([i, j + 1, i + 1, j, i + 1, j + 1])
				invert(i, j + 1, i + 1, j, i + 1, j + 1)
		elif arr[i][j] + arr[i + 1][j] + arr[i][j + 1] + arr[i + 1][j + 1] == 3:
			if arr[i][j] == 0:
				ans.append([i + 1, j, i, j + 1, i + 1, j + 1])
				invert(i + 1, j, i, j + 1, i + 1, j + 1)
			elif arr[i + 1][j] == 0:
				ans.append([i, j, i, j + 1, i + 1, j + 1])
				invert(i, j, i, j + 1, i + 1, j + 1)
			elif arr[i][j + 1] == 0:
				ans.append([i, j, i + 1, j, i + 1, j + 1])
				invert(i, j, i + 1, j, i + 1, j + 1)
			elif arr[i + 1][j + 1] == 0:
				ans.append([i, j, i + 1, j, i, j + 1])
				invert(i, j, i + 1, j, i, j + 1)
		elif arr[i][j] + arr[i + 1][j] + arr[i][j + 1] + arr[i + 1][j + 1] == 2:
			if arr[i][j] == arr[i + 1][j] == 0:
				ans.append([i, j, i + 1, j, i, j + 1])
				invert(i, j, i + 1, j, i, j + 1)
				ans.append([i, j, i + 1, j, i + 1, j + 1])
				invert(i, j, i + 1, j, i + 1, j + 1)
			elif arr[i][j] == arr[i][j + 1] == 0:
				ans.append([i, j, i, j + 1, i + 1, j + 1])
				ans.append([i, j, i, j + 1, i + 1, j])
				invert(i, j, i, j + 1, i + 1, j + 1)
				invert(i, j, i, j + 1, i + 1, j)
			elif arr[i][j] == arr[i + 1][j + 1] == 0:
				ans.append([i, j, i + 1, j + 1, i, j + 1])
				ans.append([i, j, i + 1, j + 1, i + 1, j])
				invert(i, j, i + 1, j + 1, i, j + 1)
				invert(i, j, i + 1, j + 1, i + 1, j)
			elif arr[i + 1][j] == arr[i + 1][j + 1] == 0:
				ans.append([i + 1, j, i + 1, j + 1, i, j])
				ans.append([i + 1, j, i + 1, j + 1, i, j + 1])
				invert(i + 1, j, i + 1, j + 1, i, j)
				invert(i + 1, j, i + 1, j + 1, i, j + 1)
			elif arr[i][j + 1] == arr[i + 1][j + 1] == 0:
				ans.append([i, j + 1, i + 1, j + 1, i, j])
				ans.append([i, j + 1, i + 1, j + 1, i + 1, j])
				invert(i, j + 1, i + 1, j + 1, i, j)
				invert(i, j + 1, i + 1, j + 1, i + 1, j)
			elif arr[i][j + 1] == arr[i + 1][j] == 0:
				ans.append([i, j + 1, i + 1, j, i, j])
				ans.append([i, j + 1, i + 1, j, i + 1, j + 1])
				invert(i, j + 1, i + 1, j, i, j)
				invert(i, j + 1, i + 1, j, i + 1, j + 1)
		elif arr[i][j] + arr[i + 1][j] + arr[i][j + 1] + arr[i + 1][j + 1] == 1:
			if arr[i][j] == 1:
				ans.append([i, j, i, j + 1, i + 1, j + 1])
				ans.append([i, j, i + 1, j, i, j + 1])
				ans.append([i, j, i + 1, j, i + 1, j + 1])
				invert(i, j, i, j + 1, i + 1, j + 1)
				invert(i, j, i + 1, j, i, j + 1)
				invert(i, j, i + 1, j, i + 1, j + 1)
			elif arr[i + 1][j] == 1:
				ans.append([i, j, i, j + 1, i + 1, j])
				ans.append([i, j, i + 1, j, i + 1, j + 1])
				ans.append([i, j + 1, i + 1, j, i + 1, j + 1])
				invert(i, j, i, j + 1, i + 1, j)
				invert(i, j, i + 1, j, i + 1, j + 1)
				invert(i, j + 1, i + 1, j, i + 1, j + 1)
			elif arr[i][j + 1] == 1:
				ans.append([i, j, i, j + 1, i + 1, j])
				ans.append([i, j, i, j + 1, i + 1, j + 1])
				ans.append([i, j + 1, i + 1, j, i + 1, j + 1])
				invert(i, j, i, j + 1, i + 1, j)
				invert(i, j, i, j + 1, i + 1, j + 1)
				invert(i, j + 1, i + 1, j, i + 1, j + 1)
			elif arr[i + 1][j + 1] == 1:
				ans.append([i, j, i + 1, j, i + 1, j + 1])
				ans.append([i, j + 1, i + 1, j, i + 1, j + 1])
				ans.append([i, j, i, j + 1, i + 1, j + 1])
				invert(i, j, i + 1, j, i + 1, j + 1)
				invert(i, j + 1, i + 1, j, i + 1, j + 1)
				invert(i, j, i, j + 1, i + 1, j + 1)
	print(len(ans))
	for i in ans:
		i = [j + 1 for j in i]
		print(*i)


def revab(b):
	for i in range(3):
		rev(b[2 * i], b[2 * i + 1])

def rev(x, y):
	global c
	if c[x - 1][y - 1] == '1':
		c[x - 1][y - 1] = '0'
	else:
		c[x - 1][y - 1] = '1'
import sys
for _ in range(int(sys.stdin.readline())):
	a = list(map(int, sys.stdin.readline().strip().split(' ')))
	c = []
	for i in range(a[0]):
		c.append(list(sys.stdin.readline().strip()))
	opn = 0
	ops = []
	a[0] -= 1
	while a[0] > 1:
		for i in range(a[1] - 1):
			if c[a[0]][i] == '1':
				opn += 1
				ops.append([a[0] + 1, i + 1, a[0], i + 1, a[0], i + 2])
				revab(ops[-1])
		if c[a[0]][a[1] - 1] == '1':
			opn += 1
			ops.append([a[0] + 1, a[1], a[0], a[1] - 1, a[0], a[1]])
			revab(ops[-1])
		a[0] -= 1
	a[1] -= 1
	while a[1] > 1:
		if c[0][a[1]] == '1' and c[1][a[1]] == '1':
			opn += 1
			ops.append([1, a[1] + 1, 2, a[1] + 1, 1, a[1]])
			revab(ops[-1])
		elif c[0][a[1]] == '1':
			opn += 1
			ops.append([1, a[1], 2, a[1], 1, a[1] + 1])
			revab(ops[-1])
		elif c[1][a[1]] == '1':
			opn += 1
			ops.append([2, a[1], 1, a[1], 2, a[1] + 1])
			revab(ops[-1])
		a[1] -= 1
	if c[0:2][0].count('1') + c[0:2][1].count('1') == 3 or c[0:2][0].count('1') + c[0:2][1].count('1') == 1:
		if c[0][0] == '0':
			opn += 1
			ops.append([1, 2, 2, 1, 2, 2])
		if c[1][0] == '0':
			opn += 1
			ops.append([1, 2, 1, 1, 2, 2])
		if c[0][1] == '0':
			opn += 1
			ops.append([1, 1, 2, 1, 2, 2])
		if c[1][1] == '0':
			opn += 1
			ops.append([1, 2, 2, 1, 1, 1])
	else:
		if c[0][0] == '1':
			opn += 1
			ops.append([1, 2, 2, 1, 2, 2])
		if c[1][0] == '1':
			opn += 1
			ops.append([1, 2, 1, 1, 2, 2])
		if c[0][1] == '1':
			opn += 1
			ops.append([1, 1, 2, 1, 2, 2])
		if c[1][1] == '1':
			opn += 1
			ops.append([1, 2, 2, 1, 1, 1])
	print(opn)
	for i in ops:
		print(' '.join(list(map(str, i))))


for _ in range(int(input())):
	(n, m) = map(int, input().split())
	l = []
	for i in range(n):
		s = str(input())
		t = []
		for i in range(len(s)):
			t.append(int(s[i]))
		l.append(t)
	lf = []
	for i in range(n - 2):
		for j in range(m):
			if j == m - 1:
				if l[i][j] == 1:
					lf.append([i, j, i + 1, j - 1, i + 1, j])
					l[i][j] = 0
					l[i + 1][j - 1] = 1 - l[i + 1][j - 1]
					l[i + 1][j] = 1 - l[i + 1][j]
			elif l[i][j] == 1:
				lf.append([i, j, i + 1, j + 1, i + 1, j])
				l[i][j] = 0
				l[i + 1][j + 1] = 1 - l[i + 1][j + 1]
				l[i + 1][j] = 1 - l[i + 1][j]
	if m % 2 != 0:
		if l[n - 2][m - 1] == 1:
			lf.append([n - 2, m - 1, n - 2, m - 2, n - 1, m - 2])
			l[n - 2][m - 1] = 0
			l[n - 2][m - 2] = 1 - l[n - 2][m - 2]
			l[n - 1][m - 2] = 1 - l[n - 1][m - 2]
		if l[n - 1][m - 1] == 1:
			lf.append([n - 1, m - 1, n - 2, m - 2, n - 1, m - 2])
			l[n - 1][m - 1] = 0
			l[n - 2][m - 2] = 1 - l[n - 2][m - 2]
			l[n - 1][m - 2] = 1 - l[n - 1][m - 2]
	i = n - 2
	for j in range(0, m - 1, 2):
		if l[i][j] == 1 and l[i + 1][j] == 1 and (l[i][j + 1] == 1) and (l[i + 1][j + 1] == 1):
			lf.append([i, j, i + 1, j, i, j + 1])
			lf.append([i, j, i + 1, j, i + 1, j + 1])
			lf.append([i, j, i, j + 1, i + 1, j + 1])
			lf.append([i, j + 1, i + 1, j, i + 1, j + 1])
		elif l[i][j] == 1 and l[i + 1][j] == 1 and (l[i + 1][j + 1] == 1):
			lf.append([i, j, i + 1, j, i + 1, j + 1])
		elif l[i][j] == 1 and l[i][j + 1] == 1 and (l[i + 1][j] == 1):
			lf.append([i, j, i, j + 1, i + 1, j])
		elif l[i][j] == 1 and l[i][j + 1] == 1 and (l[i + 1][j + 1] == 1):
			lf.append([i, j, i, j + 1, i + 1, j + 1])
		elif l[i][j + 1] == 1 and l[i + 1][j] == 1 and (l[i + 1][j + 1] == 1):
			lf.append([i, j + 1, i + 1, j, i + 1, j + 1])
		elif l[i][j] == 1 and l[i + 1][j] == 1:
			lf.append([i, j + 1, i + 1, j + 1, i + 1, j])
			lf.append([i, j, i, j + 1, i + 1, j + 1])
		elif l[i][j] == 1 and l[i][j + 1] == 1:
			lf.append([i, j + 1, i + 1, j, i + 1, j + 1])
			lf.append([i, j, i + 1, j + 1, i + 1, j])
		elif l[i][j + 1] == 1 and l[i + 1][j + 1] == 1:
			lf.append([i, j, i, j + 1, i + 1, j])
			lf.append([i, j, i + 1, j, i + 1, j + 1])
		elif l[i + 1][j] == 1 and l[i + 1][j + 1] == 1:
			lf.append([i, j, i + 1, j, i, j + 1])
			lf.append([i, j, i, j + 1, i + 1, j + 1])
		elif l[i][j] == 1 and l[i + 1][j + 1] == 1:
			lf.append([i, j, i + 1, j, i, j + 1])
			lf.append([i + 1, j + 1, i + 1, j, i, j + 1])
		elif l[i][j + 1] == 1 and l[i + 1][j] == 1:
			lf.append([i, j, i, j + 1, i + 1, j + 1])
			lf.append([i, j, i + 1, j, i + 1, j + 1])
		elif l[i][j] == 1:
			lf.append([i, j, i, j + 1, i + 1, j + 1])
			lf.append([i, j, i + 1, j, i + 1, j + 1])
			lf.append([i, j, i + 1, j, i, j + 1])
		elif l[i][j + 1] == 1:
			lf.append([i, j + 1, i + 1, j, i + 1, j + 1])
			lf.append([i, j, i + 1, j, i, j + 1])
			lf.append([i, j, i, j + 1, i + 1, j + 1])
		elif l[i + 1][j] == 1:
			lf.append([i, j, i, j + 1, i + 1, j])
			lf.append([i, j, i + 1, j, i + 1, j + 1])
			lf.append([i, j + 1, i + 1, j, i + 1, j + 1])
		elif l[i + 1][j + 1] == 1:
			lf.append([i, j, i + 1, j, i + 1, j + 1])
			lf.append([i, j, i, j + 1, i + 1, j + 1])
			lf.append([i + 1, j, i, j + 1, i + 1, j + 1])
	print(len(lf))
	for i in range(0, len(lf)):
		for j in range(6):
			print(lf[i][j] + 1, end=' ')
		print()


mod = 10 ** 9 + 7
for _ in range(int(input())):
	(n, m) = map(int, input().split())
	a = []
	for i in range(n):
		b = input()
		a.append([])
		for j in range(m):
			a[i].append(int(b[j]))
	res = []
	for i in range(n - 2):
		for j in range(m - 2):
			if a[i][j] == 1:
				if a[i][j + 1] == 1:
					res.append((i + 1, j + 1, i + 2, j + 1, i + 1, j + 2))
					a[i][j] = 1 - a[i][j]
					a[i + 1][j] = 1 - a[i + 1][j]
					a[i][j + 1] = 1 - a[i][j + 1]
				else:
					res.append((i + 1, j + 1, i + 2, j + 1, i + 2, j + 2))
					a[i][j] = 1 - a[i][j]
					a[i + 1][j] = 1 - a[i + 1][j]
					a[i + 1][j + 1] = 1 - a[i + 1][j + 1]
		if a[i][m - 2] == 1 and a[i][m - 1] == 1:
			res.append((i + 1, m - 1, i + 1, m, i + 2, m - 1))
			a[i][m - 2] = 1 - a[i][m - 2]
			a[i][m - 1] = 1 - a[i][m - 1]
			a[i + 1][m - 2] = 1 - a[i + 1][m - 2]
		elif a[i][m - 2] == 1:
			res.append((i + 1, m - 1, i + 2, m - 1, i + 2, m))
			a[i][m - 2] = 1 - a[i][m - 2]
			a[i + 1][m - 1] = 1 - a[i + 1][m - 1]
			a[i + 1][m - 2] = 1 - a[i + 1][m - 2]
		elif a[i][m - 1] == 1:
			res.append((i + 1, m, i + 2, m - 1, i + 2, m))
			a[i + 1][m - 1] = 1 - a[i + 1][m - 1]
			a[i][m - 1] = 1 - a[i][m - 1]
			a[i + 1][m - 2] = 1 - a[i + 1][m - 2]
	for i in range(m - 2):
		if a[n - 2][i] == 1 and a[n - 1][i] == 1:
			res.append((n - 1, i + 1, n, i + 1, n, i + 2))
			a[n - 1][i] = 1 - a[n - 1][i]
			a[n - 2][i] = 1 - a[n - 2][i]
			a[n - 1][i + 1] = 1 - a[n - 1][i + 1]
		elif a[n - 2][i] == 1:
			res.append((n - 1, i + 1, n - 1, i + 2, n, i + 2))
			a[n - 1][i + 1] = 1 - a[n - 1][i + 1]
			a[n - 2][i] = 1 - a[n - 2][i]
			a[n - 2][i + 1] = 1 - a[n - 2][i + 1]
		elif a[n - 1][i] == 1:
			res.append((n - 1, i + 2, n, i + 1, n, i + 2))
			a[n - 1][i] = 1 - a[n - 1][i]
			a[n - 1][i + 1] = 1 - a[n - 1][i + 1]
			a[n - 2][i + 1] = 1 - a[n - 2][i + 1]
	p = [(n - 1, m - 1, n - 1, m, n, m), (n - 1, m - 1, n, m - 1, n, m), (n - 1, m, n, m - 1, n, m), (n - 1, m - 1, n - 1, m, n, m - 1)]
	ct = 0
	ap = []
	az = []
	if a[n - 2][m - 2] == 1:
		ct += 1
		ap += [n - 1, m - 1]
	else:
		az += [n - 1, m - 1]
	if a[n - 2][m - 1] == 1:
		ct += 1
		ap += [n - 1, m]
	else:
		az += [n - 1, m]
	if a[n - 1][m - 2] == 1:
		ct += 1
		ap += [n, m - 1]
	else:
		az += [n, m - 1]
	if a[n - 1][m - 1] == 1:
		ct += 1
		ap += [n, m]
	else:
		az += [n, m]
	if ct == 4:
		for i in p:
			res.append(i)
	elif ct == 3:
		res.append(ap)
	elif ct == 2:
		if a[n - 2][m - 2] == 1 and a[n - 2][m - 1] == 1:
			res.append((n, m - 1, n, m, n - 1, m - 1))
			res.append((n, m - 1, n, m, n - 1, m))
		elif a[n - 1][m - 2] == 1 and a[n - 1][m - 1] == 1:
			res.append((n - 1, m - 1, n - 1, m, n, m - 1))
			res.append((n - 1, m - 1, n - 1, m, n, m))
		elif a[n - 2][m - 2] == 1 and a[n - 1][m - 2] == 1:
			res.append((n - 1, m, n, m, n - 1, m - 1))
			res.append((n - 1, m, n, m, n, m - 1))
		elif a[n - 2][m - 1] == 1 and a[n - 1][m - 1] == 1:
			res.append((n - 1, m - 1, n, m - 1, n - 1, m))
			res.append((n - 1, m - 1, n, m - 1, n, m))
		elif a[n - 2][m - 2] == 1 and a[n - 1][m - 1] == 1:
			res.append((n - 1, m, n, m - 1, n - 1, m - 1))
			res.append((n - 1, m, n, m - 1, n, m))
		elif a[n - 2][m - 1] == 1 and a[n - 1][m - 2] == 1:
			res.append((n - 1, m - 1, n, m, n - 1, m))
			res.append((n - 1, m - 1, n, m, n, m - 1))
	elif ct == 1:
		if a[n - 2][m - 2] == 1:
			res.append((n - 1, m, n, m, n - 1, m - 1))
			a[n - 2][m - 1] = 1 - a[n - 2][m - 1]
			a[n - 1][m - 1] = 1 - a[n - 1][m - 1]
			a[n - 2][m - 2] = 1 - a[n - 2][m - 2]
		elif a[n - 2][m - 1] == 1:
			res.append((n - 1, m - 1, n - 1, m, n, m))
			a[n - 2][m - 2] = 1 - a[n - 2][m - 2]
			a[n - 2][m - 1] = 1 - a[n - 2][m - 1]
			a[n - 1][m - 1] = 1 - a[n - 1][m - 1]
		elif a[n - 1][m - 2] == 1:
			res.append((n - 1, m - 1, n, m, n, m - 1))
			a[n - 2][m - 2] = 1 - a[n - 2][m - 2]
			a[n - 1][m - 1] = 1 - a[n - 1][m - 1]
			a[n - 1][m - 2] = 1 - a[n - 1][m - 2]
		elif a[n - 1][m - 1] == 1:
			res.append((n, m - 1, n, m, n - 1, m - 1))
			a[n - 1][m - 2] = 1 - a[n - 1][m - 2]
			a[n - 1][m - 1] = 1 - a[n - 1][m - 1]
			a[n - 2][m - 2] = 1 - a[n - 2][m - 2]
		if a[n - 2][m - 2] == 1 and a[n - 2][m - 1] == 1:
			res.append((n, m - 1, n, m, n - 1, m - 1))
			res.append((n, m - 1, n, m, n - 1, m))
		elif a[n - 1][m - 2] == 1 and a[n - 1][m - 1] == 1:
			res.append((n - 1, m - 1, n - 1, m, n, m - 1))
			res.append((n - 1, m - 1, n - 1, m, n, m))
		elif a[n - 2][m - 2] == 1 and a[n - 1][m - 2] == 1:
			res.append((n - 1, m, n, m, n - 1, m - 1))
			res.append((n - 1, m, n, m, n, m - 1))
		elif a[n - 2][m - 1] == 1 and a[n - 1][m - 1] == 1:
			res.append((n - 1, m - 1, n, m - 1, n - 1, m))
			res.append((n - 1, m - 1, n, m - 1, n, m))
		elif a[n - 2][m - 2] == 1 and a[n - 1][m - 1] == 1:
			res.append((n - 1, m, n, m - 1, n - 1, m - 1))
			res.append((n - 1, m, n, m - 1, n, m))
		elif a[n - 2][m - 1] == 1 and a[n - 1][m - 2] == 1:
			res.append((n - 1, m - 1, n, m, n - 1, m))
			res.append((n - 1, m - 1, n, m, n, m - 1))
	print(len(res))
	for i in res:
		print(*i)


from sys import stdin, stdout
t = int(stdin.readline())

def flip(c):
	if c == '0':
		return '1'
	else:
		return '0'
lookup = {(0, 0, 0, 0): 'NIL', (0, 0, 0, 1): (['1', '1', '1', '2', '2', '2'], (1, 1, 0, 0)), (0, 0, 1, 0): (['1', '2', '2', '1', '2', '2'], (0, 1, 0, 1)), (0, 0, 1, 1): (['1', '1', '1', '2', '2', '2'], (1, 1, 1, 0)), (0, 1, 0, 0): (['1', '1', '1', '2', '2', '1'], (1, 0, 1, 0)), (0, 1, 0, 1): (['1', '1', '1', '2', '2', '1'], (1, 0, 1, 1)), (0, 1, 1, 0): (['1', '1', '1', '2', '2', '1'], (1, 0, 0, 0)), (0, 1, 1, 1): (['2', '1', '1', '2', '2', '2'], (0, 0, 0, 0)), (1, 0, 0, 0): (['1', '1', '2', '1', '2', '2'], (0, 0, 1, 1)), (1, 0, 0, 1): (['1', '1', '1', '2', '2', '2'], (0, 1, 0, 0)), (1, 0, 1, 0): (['1', '2', '2', '1', '2', '2'], (1, 1, 0, 1)), (1, 0, 1, 1): (['1', '1', '2', '1', '2', '2'], (0, 0, 0, 0)), (1, 1, 0, 0): (['1', '1', '2', '1', '2', '2'], (0, 1, 1, 1)), (1, 1, 0, 1): (['1', '1', '1', '2', '2', '2'], (0, 0, 0, 0)), (1, 1, 1, 0): (['1', '1', '1', '2', '2', '1'], (0, 0, 0, 0)), (1, 1, 1, 1): (['1', '1', '1', '2', '2', '1'], (0, 0, 0, 1))}
for _ in range(t):
	(n, m) = [int(x) for x in stdin.readline().split()]
	table = []
	for foo in range(n):
		table.append([c for c in stdin.readline().strip()])
	answer = []
	for i in range(n - 1, 1, -1):
		for j in range(m):
			if j == 0:
				if table[i][j] == '1':
					answer.append([str(i + 1), str(j + 1), str(i), str(j + 1), str(i), str(j + 2)])
					table[i - 1][j] = flip(table[i - 1][j])
					table[i - 1][j + 1] = flip(table[i - 1][j + 1])
			elif table[i][j] == '1':
				answer.append([str(i + 1), str(j + 1), str(i), str(j + 1), str(i), str(j)])
				table[i - 1][j] = flip(table[i - 1][j])
				table[i - 1][j - 1] = flip(table[i - 1][j - 1])
	for j in range(m - 1, 1, -1):
		if table[0][j] == '1':
			answer.append(['1', str(j + 1), '1', str(j), '2', str(j)])
			table[0][j - 1] = flip(table[0][j - 1])
			table[1][j - 1] = flip(table[1][j - 1])
		if table[1][j] == '1':
			answer.append(['2', str(j + 1), '1', str(j), '2', str(j)])
			table[0][j - 1] = flip(table[0][j - 1])
			table[1][j - 1] = flip(table[1][j - 1])
	current = (int(table[0][0]), int(table[0][1]), int(table[1][0]), int(table[1][1]))
	while lookup[current] != 'NIL':
		answer.append(lookup[current][0])
		current = lookup[current][1]
	stdout.write(str(len(answer)) + '\n')
	for a in answer:
		stdout.write(' '.join(a) + '\n')


import sys

def input():
	return sys.stdin.readline().strip()

def list2d(a, b, c):
	return [[c] * b for i in range(a)]

def list3d(a, b, c, d):
	return [[[d] * c for k in range(b)] for i in range(a)]

def list4d(a, b, c, d, e):
	return [[[[e] * d for k in range(c)] for k in range(b)] for i in range(a)]

def ceil(x, y=1):
	return int(-(-x // y))

def INT():
	return int(input())

def MAP():
	return map(int, input().split())

def LIST(N=None):
	return list(MAP()) if N is None else [INT() for i in range(N)]

def Yes():
	print('Yes')

def No():
	print('No')

def YES():
	print('YES')

def NO():
	print('NO')
INF = 10 ** 19
MOD = 10 ** 9 + 7
EPS = 10 ** (-10)

def check1(i, j):
	pattern = [[(i, j), (i + 1, j), (i, j + 1)], [(i + 1, j), (i, j + 1), (i + 1, j + 1)], [(i, j + 1), (i + 1, j + 1), (i, j)], [(i + 1, j + 1), (i, j), (i + 1, j)]]
	for bit in range(1 << 4):
		res = []
		for k in range(4):
			if bit >> k & 1:
				row = []
				for (h, w) in pattern[k]:
					grid[h][w] ^= 1
					row += [h, w]
				res.append(row)
		cnt = 0
		for h in range(i, i + 2):
			for w in range(j, j + 2):
				cnt += grid[h][w]
		for k in range(4):
			if bit >> k & 1:
				for (h, w) in pattern[k]:
					grid[h][w] ^= 1
		if not cnt:
			return res
	raise Exception

def check2(i, j):
	res = []
	if grid[i][j] and grid[i - 1][j]:
		res.append([i, j, i, j - 1, i - 1, j - 1])
		res.append([i - 1, j, i, j - 1, i - 1, j - 1])
	elif grid[i][j]:
		res.append([i, j, i, j - 1, i - 1, j - 1])
		grid[i][j - 1] ^= 1
		grid[i - 1][j - 1] ^= 1
	elif grid[i - 1][j]:
		res.append([i - 1, j, i, j - 1, i - 1, j - 1])
		grid[i][j - 1] ^= 1
		grid[i - 1][j - 1] ^= 1
	grid[i][j] = grid[i - 1][j] = 0
	return res
for _ in range(INT()):
	(H, W) = MAP()
	grid = [[]] * H
	for i in range(H):
		grid[i] = list(map(int, input()))
	ans = []
	if H % 2 == 1:
		grid = [list(row) for row in list(zip(*grid))]
		(H, W) = (W, H)
		for i in range(1, H):
			res = check2(i, W - 1)
			if res:
				for k in range(len(res)):
					for l in range(0, 6, 2):
						(res[k][l], res[k][l + 1]) = (res[k][l + 1], res[k][l])
				ans += res
		grid = [list(row) for row in list(zip(*grid))]
		(H, W) = (W, H)
	if W % 2 == 1:
		for i in range(1, H):
			ans += check2(i, W - 1)
	for i in range(0, H - H % 2, 2):
		for j in range(0, W - W % 2, 2):
			ans += check1(i, j)
	print(len(ans))
	for row in ans:
		print(*[a + 1 for a in row])


def special(xx):
	global ans, ar, mai
	left = 3
	(x1, y1) = (xx[0][0], xx[0][1])
	(x2, y2) = (xx[1][0], xx[1][1])
	(x3, y3) = (xx[2][0], xx[2][1])
	(x4, y4) = (xx[3][0], xx[3][1])
	if ar[x1][y1] != 0 or ar[x3][y3] != 0:
		ans += 1
		mai.append([])
		if ar[x1][y1] != 0:
			left -= 1
			mai[-1].append(x1 + 1)
			mai[-1].append(y1 + 1)
			ar[x1][y1] = 0
		if ar[x3][y3] != 0:
			mai[-1].append(x3 + 1)
			mai[-1].append(y3 + 1)
			left -= 1
			ar[x3][y3] = 0
		if left != 0:
			ar[x2][y2] = abs(ar[x2][y2] - 1)
			mai[-1].append(x2 + 1)
			mai[-1].append(y2 + 1)
			left -= 1
		if left != 0:
			ar[x4][y4] = abs(ar[x4][y4] - 1)
			mai[-1].append(x4 + 1)
			mai[-1].append(y4 + 1)

def special2(xx):
	global ans, ar, mai
	left = 3
	(x1, y1) = (xx[0][0], xx[0][1])
	(x3, y3) = (xx[1][0], xx[1][1])
	(x2, y2) = (xx[2][0], xx[2][1])
	(x4, y4) = (xx[3][0], xx[3][1])
	if ar[x1][y1] != 0 or ar[x3][y3] != 0:
		ans += 1
		mai.append([])
		if ar[x1][y1] != 0:
			left -= 1
			mai[-1].append(x1 + 1)
			mai[-1].append(y1 + 1)
			ar[x1][y1] = 0
		if ar[x3][y3] != 0:
			mai[-1].append(x3 + 1)
			mai[-1].append(y3 + 1)
			left -= 1
			ar[x3][y3] = 0
		if left != 0:
			ar[x2][y2] = abs(ar[x2][y2] - 1)
			mai[-1].append(x2 + 1)
			mai[-1].append(y2 + 1)
			left -= 1
		if left != 0:
			ar[x4][y4] = abs(ar[x4][y4] - 1)
			mai[-1].append(x4 + 1)
			mai[-1].append(y4 + 1)

def fun1(xx):
	global ar, ans, mai
	zer = []
	one = []
	for i in xx:
		if ar[i[0]][i[1]] == 0:
			zer.append([i[0], i[1]])
		else:
			one.append([i[0], i[1]])
	ans += 2
	mai.append([])
	for i in zer:
		mai[-1].append(i[0] + 1)
		mai[-1].append(i[1] + 1)
		ar[i[0]][i[1]] = 1
	for i in one:
		mai[-1].append(i[0] + 1)
		mai[-1].append(i[1] + 1)
		ar[i[0]][i[1]] = 0
		break
	del one[0]
	mai.append([])
	for i in zer:
		mai[-1].append(i[0] + 1)
		mai[-1].append(i[1] + 1)
		ar[i[0]][i[1]] = 0
	for i in one:
		mai[-1].append(i[0] + 1)
		mai[-1].append(i[1] + 1)
		ar[i[0]][i[1]] = 0

def fun2(xx):
	global ar, ans, mai
	zer = []
	one = []
	for i in xx:
		if ar[i[0]][i[1]] == 0:
			zer.append([i[0], i[1]])
		else:
			one.append([i[0], i[1]])
	ans += 1
	mai.append([])
	zer.pop()
	for i in zer:
		mai[-1].append(i[0] + 1)
		mai[-1].append(i[1] + 1)
		ar[i[0]][i[1]] = 1
	for i in one:
		mai[-1].append(i[0] + 1)
		mai[-1].append(i[1] + 1)
		ar[i[0]][i[1]] = 0
	fun1(xx)

def fun3(xx):
	global ar, ans, mai
	zer = []
	one = []
	for i in xx:
		if ar[i[0]][i[1]] == 0:
			zer.append([i[0], i[1]])
		else:
			one.append([i[0], i[1]])
	ans += 1
	mai.append([])
	for i in one:
		mai[-1].append(i[0] + 1)
		mai[-1].append(i[1] + 1)
		ar[i[0]][i[1]] = 0
for _ in range(int(input())):
	(n, m) = map(int, input().split())
	ans = 0
	mai = []
	ar = []
	if m != 2:
		for i in range(n):
			ar.append(list(map(int, list(input()))))
		for i in range(n - 1):
			for j in range(m - 1):
				special([[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]])
		for i in range(n - 1):
			j = m - 2
			special2([[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]])
		i = n - 2
		j = m - 2
		zero = 0
		one = 0
		if ar[i][j] == 0:
			zero += 1
		else:
			one += 1
		if ar[i + 1][j] == 0:
			zero += 1
		else:
			one += 1
		if ar[i][j + 1] == 0:
			zero += 1
		else:
			one += 1
		if ar[i + 1][j + 1] == 0:
			zero += 1
		else:
			one += 1
		if one == 2 and zero == 2:
			fun1([[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]])
		elif zero == 3 and one == 1:
			fun2([[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]])
		print(ans)
		for i in mai:
			print(*i)
	else:
		for i in range(n):
			ar.append(list(map(int, list(input()))))
		for i in range(n - 1):
			for j in range(m - 1):
				zero = 0
				one = 0
				if ar[i][j] == 0:
					zero += 1
				else:
					one += 1
				if ar[i + 1][j] == 0:
					zero += 1
				else:
					one += 1
				if ar[i][j + 1] == 0:
					zero += 1
				else:
					one += 1
				if ar[i + 1][j + 1] == 0:
					zero += 1
				else:
					one += 1
				if one == 4:
					ans += 1
					mai.append([])
					mai[-1].append(i + 1)
					mai[-1].append(j + 1)
					mai[-1].append(i + 2)
					mai[-1].append(j + 1)
					mai[-1].append(i + 1)
					mai[-1].append(j + 2)
					ar[i][j] = 0
					ar[i][j + 1] = 0
					ar[i + 1][j] = 0
				elif one == 2 and zero == 2:
					fun1([[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]])
				elif zero == 3 and one == 1:
					fun2([[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]])
				elif one == 3:
					fun3([[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]])
		zero = 0
		one = 0
		if ar[i][j] == 0:
			zero += 1
		else:
			one += 1
		if ar[i + 1][j] == 0:
			zero += 1
		else:
			one += 1
		if ar[i][j + 1] == 0:
			zero += 1
		else:
			one += 1
		if ar[i + 1][j + 1] == 0:
			zero += 1
		else:
			one += 1
		if one == 4:
			ans += 1
			mai.append([])
			mai[-1].append(i + 1)
			mai[-1].append(j + 1)
			mai[-1].append(i + 2)
			mai[-1].append(j + 1)
			mai[-1].append(i + 1)
			mai[-1].append(j + 2)
			ar[i][j] = 0
			ar[i][j + 1] = 0
			ar[i + 1][j] = 0
		elif one == 2 and zero == 2:
			fun1([[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]])
		elif zero == 3 and one == 1:
			fun2([[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]])
		elif one == 3:
			fun3([[i, j], [i, j + 1], [i + 1, j], [i + 1, j + 1]])
		print(ans)
		for i in mai:
			print(*i)


import sys
input = sys.stdin.readline
from collections import *

def tran():
	pos = []
	epos = []
	for i in range(n - 2, n):
		for j in range(m - 2, m):
			if s[i][j] == 1:
				pos.append((i, j))
			else:
				epos.append((i, j))
	if len(pos) in [1, 2]:
		row = (pos[0][0], pos[0][1], epos[0][0], epos[0][1], epos[1][0], epos[1][1])
		ans.append(row)
		for j in range(3):
			x = row[2 * j]
			y = row[2 * j + 1]
			s[x][y] ^= 1
	else:
		row = (pos[0][0], pos[0][1], pos[1][0], pos[1][1], pos[2][0], pos[2][1])
		ans.append(row)
		for j in range(3):
			x = row[2 * j]
			y = row[2 * j + 1]
			s[x][y] ^= 1
t = int(input())
for _ in range(t):
	(n, m) = map(int, input().split())
	s = [list(map(int, input()[:-1])) for _ in range(n)]
	ans = []
	for i in range(n - 1):
		for j in range(m - 1):
			if i == n - 2 and j == m - 2:
				continue
			if s[i][j] == 1:
				ans.append((i, j, i + 1, j, i, j + 1))
				s[i][j] ^= 1
				s[i + 1][j] ^= 1
				s[i][j + 1] ^= 1
	for i in range(m - 2):
		if s[n - 2][i] == 1 and s[n - 1][i] == 1:
			row = (n - 2, i, n - 1, i, n - 2, i + 1)
		elif s[n - 2][i] == 1 and s[n - 1][i] == 0:
			row = (n - 2, i, n - 2, i + 1, n - 1, i + 1)
		elif s[n - 2][i] == 0 and s[n - 1][i] == 1:
			row = (n - 1, i, n - 2, i + 1, n - 1, i + 1)
		else:
			continue
		for j in range(3):
			x = row[2 * j]
			y = row[2 * j + 1]
			s[x][y] ^= 1
		ans.append(row)
	for i in range(n - 2):
		if s[i][m - 2] == 1 and s[i][m - 1] == 1:
			row = (i, m - 2, i, m - 1, i + 1, m - 2)
		elif s[i][m - 2] == 1 and s[i][m - 1] == 0:
			row = (i, m - 2, i + 1, m - 2, i + 1, m - 1)
		elif s[i][m - 2] == 0 and s[i][m - 1] == 1:
			row = (i, m - 1, i + 1, m - 2, i + 1, m - 1)
		else:
			continue
		for j in range(3):
			x = row[2 * j]
			y = row[2 * j + 1]
			s[x][y] ^= 1
		ans.append(row)
	while s[n - 2][m - 2] == 1 or s[n - 2][m - 1] == 1 or s[n - 1][m - 2] == 1 or (s[n - 1][m - 1] == 1):
		tran()
	for i in range(n):
		for j in range(m):
			if s[i][j] == 1:
				1 / 0
	print(len(ans))
	for (a, b, c, d, e, f) in ans:
		print(a + 1, b + 1, c + 1, d + 1, e + 1, f + 1)


import sys
from collections import defaultdict
input = lambda : sys.stdin.readline().rstrip()

def comp(t):
	return (t[0] << 50) + (t[1] << 40) + (t[2] << 30) + (t[3] << 20) + (t[4] << 10) + t[5]

def decomp(n):
	ret = []
	for _ in range(6):
		ret.append(n & (1 << 10) - 1)
		n >>= 10
	return tuple(reversed(ret))
t = int(input())
for _ in range(t):
	(n, m) = map(int, input().split())
	field = [list(map(int, input())) for _ in range(n)]
	ans = defaultdict(int)
	for i in range(n - 1):
		j = 0
		while j < m:
			while j < m and field[i][j] == 0:
				j += 1
			if j < m:
				if j + 1 < m:
					if field[i][j + 1] == 1:
						ans[comp((i, j, i, j + 1, i + 1, j))] ^= 1
						field[i][j] ^= 1
						field[i][j + 1] ^= 1
						field[i + 1][j] ^= 1
					else:
						ans[comp((i, j, i + 1, j, i + 1, j + 1))] ^= 1
						field[i][j] ^= 1
						field[i + 1][j + 1] ^= 1
						field[i + 1][j] ^= 1
				else:
					ans[comp((i, j, i + 1, j - 1, i + 1, j))] ^= 1
					field[i][j] ^= 1
					field[i + 1][j - 1] ^= 1
					field[i + 1][j] ^= 1
			j += 2
	i = n - 1
	j = 0
	while j < m:
		while j < m and field[i][j] == 0:
			j += 1
		if j < m:
			if j + 1 < m:
				if field[i][j + 1] == 1:
					t = (i - 1, j, i - 1, j + 1, i, j)
					it = iter(t)
					for (ni, nj) in zip(it, it):
						field[ni][nj] ^= 1
					ans[comp(t)] ^= 1
					t = (i - 1, j, i - 1, j + 1, i, j + 1)
					it = iter(t)
					for (ni, nj) in zip(it, it):
						field[ni][nj] ^= 1
					ans[comp(t)] ^= 1
				elif j + 2 < m and field[i][j + 2] == 1:
					t = (i - 1, j + 1, i, j, i, j + 1)
					it = iter(t)
					for (ni, nj) in zip(it, it):
						field[ni][nj] ^= 1
					ans[comp(t)] ^= 1
					t = (i - 1, j + 1, i, j + 1, i, j + 2)
					it = iter(t)
					for (ni, nj) in zip(it, it):
						field[ni][nj] ^= 1
					ans[comp(t)] ^= 1
				else:
					t = (i - 1, j, i - 1, j + 1, i, j)
					it = iter(t)
					for (ni, nj) in zip(it, it):
						field[ni][nj] ^= 1
					ans[comp(t)] ^= 1
					t = (i - 1, j, i, j, i, j + 1)
					it = iter(t)
					for (ni, nj) in zip(it, it):
						field[ni][nj] ^= 1
					ans[comp(t)] ^= 1
					t = (i - 1, j + 1, i, j, i, j + 1)
					it = iter(t)
					for (ni, nj) in zip(it, it):
						field[ni][nj] ^= 1
					ans[comp(t)] ^= 1
			else:
				t = (i - 1, j - 1, i - 1, j, i, j)
				it = iter(t)
				for (ni, nj) in zip(it, it):
					field[ni][nj] ^= 1
				ans[comp(t)] ^= 1
				t = (i - 1, j, i, j - 1, i, j)
				it = iter(t)
				for (ni, nj) in zip(it, it):
					field[ni][nj] ^= 1
				ans[comp(t)] ^= 1
				t = (i - 1, j - 1, i, j - 1, i, j)
				it = iter(t)
				for (ni, nj) in zip(it, it):
					field[ni][nj] ^= 1
				ans[comp(t)] ^= 1
			j += 2
	newans = []
	for (k, v) in ans.items():
		if v:
			newans.append(decomp(k))
	print(len(newans))
	for line in newans:
		print(*[l + 1 for l in line])


import sys
input = lambda : sys.stdin.readline().strip()
inp = lambda : list(map(int, sys.stdin.readline().strip().split()))
for _ in range(int(input())):
	(n, m) = inp()
	a = [[i for i in str(input())] for j in range(n)]
	ans = []

	def change(lol):
		(b, c, d, e, f, g) = lol
		a[b - 1][c - 1] = '0' if a[b - 1][c - 1] == '1' else '1'
		a[d - 1][e - 1] = '0' if a[d - 1][e - 1] == '1' else '1'
		a[f - 1][g - 1] = '0' if a[f - 1][g - 1] == '1' else '1'
	for i in range(1, n - 1):
		for j in range(1, m - 1):
			if a[i - 1][j - 1] == '1':
				ans.append([i, j, i + 1, j, i + 1, j + 1])
				change([i, j, i + 1, j, i + 1, j + 1])
	a1 = m - 1
	a2 = m
	for i in range(1, n - 1):
		if a[i - 1][a1 - 1] == '1' and a[i - 1][a2 - 1] == '1':
			ans.append([i, a1, i, a2, i + 1, a1])
		elif a[i - 1][a1 - 1] == '1' and a[i - 1][a2 - 1] == '0':
			ans.append([i, a1, i + 1, a1, i + 1, a2])
		elif a[i - 1][a1 - 1] == '0' and a[i - 1][a2 - 1] == '1':
			ans.append([i, a2, i + 1, a1, i + 1, a2])
		else:
			continue
		change(ans[-1])
	a1 = n - 1
	a2 = n
	for i in range(1, m - 1):
		if a[a1 - 1][i - 1] == '1' and a[a2 - 1][i - 1] == '1':
			ans.append([a1, i, a2, i, a1, i + 1])
		elif a[a1 - 1][i - 1] == '1' and a[a2 - 1][i - 1] == '0':
			ans.append([a1, i, a1, i + 1, a2, i + 1])
		elif a[a1 - 1][i - 1] == '0' and a[a2 - 1][i - 1] == '1':
			ans.append([a2, i, a1, i + 1, a2, i + 1])
		else:
			continue
		change(ans[-1])
	(a1, a2) = (n - 2, n - 1)
	(b1, b2) = (m - 2, m - 1)
	b = [a[a1][b1], a[a1][b2], a[a2][b1], a[a2][b2]]
	one = []
	zer = []
	if a[a1][b1] == '1':
		one.append([a1 + 1, b1 + 1])
	else:
		zer.append([a1 + 1, b1 + 1])
	if a[a1][b2] == '1':
		one.append([a1 + 1, b2 + 1])
	else:
		zer.append([a1 + 1, b2 + 1])
	if a[a2][b1] == '1':
		one.append([a2 + 1, b1 + 1])
	else:
		zer.append([a2 + 1, b1 + 1])
	if a[a2][b2] == '1':
		one.append([a2 + 1, b2 + 1])
	else:
		zer.append([a2 + 1, b2 + 1])
	if b.count('1') == 1:
		ans.append([one[0][0], one[0][1], zer[0][0], zer[0][1], zer[1][0], zer[1][1]])
		newzer = [[one[0][0], one[0][1]], [zer[2][0], zer[2][1]]]
		one = [[zer[0][0], zer[0][1]], [zer[1][0], zer[1][1]]]
		zer = newzer.copy()
	if b.count('1') == 0:
		pass
	elif b.count('1') == 3:
		ans.append([one[0][0], one[0][1], one[1][0], one[1][1], one[2][0], one[2][1]])
	elif b.count('1') == 4:
		ans.append([one[0][0], one[0][1], one[1][0], one[1][1], one[2][0], one[2][1]])
		ans.append([one[0][0], one[0][1], one[3][0], one[3][1], one[2][0], one[2][1]])
		ans.append([one[3][0], one[3][1], one[1][0], one[1][1], one[2][0], one[2][1]])
		ans.append([one[0][0], one[0][1], one[1][0], one[1][1], one[3][0], one[3][1]])
	else:
		ans.append([zer[0][0], zer[0][1], zer[1][0], zer[1][1], one[1][0], one[1][1]])
		ans.append([zer[0][0], zer[0][1], zer[1][0], zer[1][1], one[0][0], one[0][1]])
	print(len(ans))
	for i in ans:
		print(*i)


res = []

def move(table, tup):
	(a, b, c, d, e, f) = tup
	res.append((a, b, c, d, e, f))
	table[a][b] = 1 - table[a][b]
	table[c][d] = 1 - table[c][d]
	table[e][f] = 1 - table[e][f]

def solve22(n1, m1, n, m, table):
	cur = [table[n1][m1], table[n1][m1 + 1], table[n1 + 1][m1], table[n1 + 1][m1 + 1]]
	if cur == [0, 0, 0, 0]:
		return
	cnt1 = 0
	for c in cur:
		if c == 1:
			cnt1 += 1
	l = []
	if cnt1 == 3:
		for n2 in range(n1, n):
			for m2 in range(m1, m):
				if table[n2][m2] == 1:
					l += [n2, m2]
		move(table, tuple(l))
	else:
		for n2 in range(n1, n):
			for m2 in range(m1, m):
				if table[n2][m2] == 1:
					l += [n2, m2]
					if n2 - 1 >= n1:
						l += [n2 - 1, m2]
					if n2 + 1 < n:
						l += [n2 + 1, m2]
					if m2 - 1 >= m1:
						l += [n2, m2 - 1]
					if m2 + 1 < m:
						l += [n2, m2 + 1]
					move(table, tuple(l))
					solve22(n1, m1, n, m, table)
					return

def solve2m(n1, m1, n, m, table):
	if m - m1 == 2:
		solve22(n1, m1, n, m, table)
		return
	if table[n1][m1] == 1 and table[n1 + 1][m1] == 1:
		t = (n1, m1, n1 + 1, m1, n1, m1 + 1)
		move(table, t)
	elif table[n1][m1] == 1 and table[n1 + 1][m1] == 0:
		t = (n1, m1, n1 + 1, m1 + 1, n1, m1 + 1)
		move(table, t)
	elif table[n1][m1] == 0 and table[n1 + 1][m1] == 1:
		t = (n1 + 1, m1, n1 + 1, m1 + 1, n1, m1 + 1)
		move(table, t)
	solve2m(n1, m1 + 1, n, m, table)

def solve(n1, m1, n, m, table):
	if n - n1 == 2:
		solve2m(n1, m1, n, m, table)
		return
	for j in range(0, m - 1):
		if table[n1][j] == 1:
			t = (n1, j, n1 + 1, j, n1 + 1, j + 1)
			move(table, t)
	if table[n1][m - 1] == 1:
		t = (n1, m - 1, n1 + 1, m - 1, n1 + 1, m - 2)
		move(table, t)
	solve(n1 + 1, m1, n, m, table)
t = int(input())
for tt in range(t):
	(n, m) = map(int, input().split())
	table = []
	res = []
	for i in range(n):
		row = input()
		table.append(row)
	table = [[ord(c) - ord('0') for c in row] for row in table]
	solve(0, 0, n, m, table)
	print(len(res))
	for (a, b, c, d, e, f) in res:
		print(a + 1, b + 1, c + 1, d + 1, e + 1, f + 1)


def correct(x, y):
	a[x][y] = 0
	ans.append([x + 1, y + 1, x + 2, y + 1, x + 2, y + 2])
	a[x + 1][y + 1] = 1 - a[x + 1][y + 1]
	a[x + 1][y] = 1 - a[x + 1][y]

def makeone(i):
	a[-1][i] = a[-1][i + 1] = a[-2][i] = a[-2][i + 1] = 0

def one(i):
	if a[-2][i]:
		ans.append([n - 1, i + 2, n, i + 1, n - 1, i + 1])
		a[-2][i] = 0
		a[-2][i + 1] = a[-1][i] = 1
	elif a[-2][i + 1]:
		ans.append([n - 1, i + 1, n, i + 1, n - 1, i + 2])
		a[-2][i + 1] = 0
		a[-2][i] = a[-1][i] = 1
	elif a[-1][i]:
		ans.append([n - 1, i + 1, n - 1, i + 2, n, i + 1])
		a[-1][i] = 0
		a[-2][i] = a[-2][i + 1] = 1
	else:
		ans.append([n - 1, i + 1, n - 1, i + 2, n, i + 2])
		a[-1][i + 1] = 0
		a[-2][i] = a[-2][i + 1] = 1
	two(i)

def two(i):
	if a[-1][i]:
		if a[-1][i + 1]:
			ans.append([n - 1, i + 1, n - 1, i + 2, n, i + 1])
			ans.append([n - 1, i + 1, n - 1, i + 2, n, i + 2])
		elif a[-2][i]:
			ans.append([n - 1, i + 2, n, i + 2, n, i + 1])
			ans.append([n - 1, i + 2, n - 1, i + 1, n, i + 2])
		elif a[-2][i + 1]:
			ans.append([n - 1, i + 1, n - 1, i + 2, n, i + 2])
			ans.append([n - 1, i + 1, n, i + 1, n, i + 2])
	elif a[-2][i]:
		if a[-2][i + 1]:
			ans.append([n - 1, i + 2, n, i + 2, n, i + 1])
			ans.append([n - 1, i + 1, n, i + 1, n, i + 2])
		elif a[-1][i + 1]:
			ans.append([n - 1, i + 2, n, i + 2, n, i + 1])
			ans.append([n - 1, i + 1, n - 1, i + 2, n, i + 1])
	else:
		ans.append([n - 1, i + 1, n - 1, i + 2, n, i + 1])
		ans.append([n - 1, i + 1, n, i + 1, n, i + 2])
	makeone(i)

def final(i, c):
	if c == 1:
		one(i)
	elif c == 4:
		ans.append([n - 1, i + 2, n, i + 1, n, i + 2])
		a[-2][i + 1] = a[-1][i] = a[-1][i + 1] = 0
		one(i)
	elif c == 3:
		if not a[-2][i]:
			ans.append([n - 1, i + 2, n, i + 1, n, i + 2])
		elif not a[-2][i + 1]:
			ans.append([n - 1, i + 1, n, i + 1, n, i + 2])
		elif not a[-1][i]:
			ans.append([n - 1, i + 1, n - 1, i + 2, n, i + 2])
		else:
			ans.append([n - 1, i + 1, n - 1, i + 2, n, i + 1])
		makeone(i)
	elif c == 2:
		two(i)

def count(i):
	c = 0
	if a[-1][i]:
		c += 1
	if a[-1][i + 1]:
		c += 1
	if a[-2][i]:
		c += 1
	if a[-2][i + 1]:
		c += 1
	final(i, c)
for nt in range(int(input())):
	(n, m) = map(int, input().split())
	(a, ans) = ([], [])
	for i in range(n):
		a.append(list(map(int, list(input()))))
	for i in range(n - 2):
		for j in range(m - 1):
			if a[i][j] == 1:
				correct(i, j)
		if a[i][-1] == 1:
			ans.append([i + 1, m, i + 2, m, i + 2, m - 1])
			a[i][-1] = 0
			a[i + 1][-1] = 1 - a[i + 1][-1]
			a[i + 1][-2] = 1 - a[i + 1][-2]
	if m % 2:
		if a[-1][-1] and a[-2][-1]:
			for i in range(0, m - 1, 2):
				count(i)
			count(m - 2)
		elif not a[-1][-1] and (not a[-2][-1]):
			for i in range(0, m - 1, 2):
				count(i)
		else:
			for i in range(0, m - 3, 2):
				count(i)
			if a[-1][-1]:
				ans.append([n - 1, m - 1, n, m - 1, n, m])
				a[-2][-2] = 1 - a[-2][-2]
				a[-1][-2] = 1 - a[-1][-2]
				a[-1][-1] = 0
				count(m - 3)
			else:
				ans.append([n - 1, m - 1, n, m - 1, n - 1, m])
				a[-2][-2] = 1 - a[-2][-2]
				a[-1][-2] = 1 - a[-1][-2]
				a[-2][-1] = 0
				count(m - 3)
	else:
		for i in range(0, m, 2):
			count(i)
	print(len(ans))
	for i in ans:
		print(*i)


from sys import stdin
input = stdin.readline

def getAns(n, m, g):
	moves = [[]] * (m * n)
	move = [0]

	def flip(r1, c1, r2, c2, r3, c3):
		g[r1][c1] = not g[r1][c1]
		g[r2][c2] = not g[r2][c2]
		g[r3][c3] = not g[r3][c3]
		moves[move[0]] = [r1 + 1, c1 + 1, r2 + 1, c2 + 1, r3 + 1, c3 + 1]
		move[0] += 1
	for r in range(0, n - 2, 2):
		for c in range(0, m - 2):
			if not g[r][c] and g[r + 1][c]:
				flip(r + 1, c, r + 1, c + 1, r, c + 1)
			elif g[r][c] and (not g[r + 1][c]):
				flip(r, c, r + 1, c + 1, r, c + 1)
			elif g[r][c] and g[r + 1][c]:
				flip(r, c, r + 1, c, r + 1, c + 1)
	for r in range(0, n - 2):
		if not g[r][m - 2] and g[r][m - 1]:
			flip(r, m - 1, r + 1, m - 1, r + 1, m - 2)
		elif g[r][m - 2] and (not g[r][m - 1]):
			flip(r, m - 2, r + 1, m - 1, r + 1, m - 2)
		elif g[r][m - 2] and g[r][m - 1]:
			flip(r, m - 2, r, m - 1, r + 1, m - 1)
	for c in range(0, m - 1):
		if not g[n - 2][c] and g[n - 1][c]:
			flip(n - 1, c, n - 1, c + 1, n - 2, c + 1)
		elif g[n - 2][c] and (not g[n - 1][c]):
			flip(n - 2, c, n - 2, c + 1, n - 1, c + 1)
		elif g[n - 2][c] and g[n - 1][c]:
			flip(n - 2, c, n - 1, c, n - 1, c + 1)
	if g[n - 1][m - 1] and g[n - 2][m - 1]:
		flip(n - 2, m - 1, n - 1, m - 2, n - 2, m - 2)
		flip(n - 2, m - 2, n - 1, m - 2, n - 1, m - 1)
	elif g[n - 1][m - 1] and (not g[n - 2][m - 1]):
		flip(n - 2, m - 2, n - 1, m - 2, n - 1, m - 1)
		flip(n - 2, m - 2, n - 1, m - 1, n - 2, m - 1)
		flip(n - 1, m - 2, n - 1, m - 1, n - 2, m - 1)
	elif not g[n - 1][m - 1] and g[n - 2][m - 1]:
		flip(n - 2, m - 2, n - 2, m - 1, n - 1, m - 2)
		flip(n - 2, m - 2, n - 2, m - 1, n - 1, m - 1)
		flip(n - 2, m - 1, n - 1, m - 2, n - 1, m - 1)
	print(move[0])
	for i in range(move[0]):
		print(*moves[i])
for _ in range(int(input())):
	(n, m) = map(int, input().split())
	g = [0] * n
	for i in range(n):
		g[i] = [bool(int(x)) for x in input().rstrip()]
	getAns(n, m, g)


from itertools import product
result = []

def count_one(bd, r, c, rsz, csz):
	cc = 0
	for (i, j) in product(range(rsz), range(csz)):
		cc += bd[r + i][c + j] == '1'
	return cc

def apply_change(bd, res):
	for (u, v) in res:
		bd[u][v] = '0' if bd[u][v] == '1' else '1'

def print_res(res):
	result.append(res)

def pick_one(bd, r, c, one):
	(res, zero) = ([], 3 - one)
	for (i, j) in product(range(2), range(2)):
		if bd[r + i][c + j] == '1' and one:
			res.append((r + i, c + j))
			one -= 1
		elif bd[r + i][c + j] == '0' and zero:
			res.append((r + i, c + j))
			zero -= 1
	apply_change(bd, res)
	print_res(res)

def remove_one(bd, r, c, dir):
	res = []
	if dir == 'top':
		if bd[r][c] == '0' and bd[r][c + 1] == '1':
			res = [(r, c + 1), (r + 1, c), (r + 1, c + 1)]
		elif bd[r][c] == '1' and bd[r][c + 1] == '0':
			res = [(r, c), (r + 1, c), (r + 1, c + 1)]
		elif bd[r][c] == '1' and bd[r][c + 1] == '1':
			res = [(r, c), (r, c + 1), (r + 1, c)]
	elif bd[r][c] == '0' and bd[r + 1][c] == '1':
		res = [(r + 1, c), (r, c + 1), (r + 1, c + 1)]
	elif bd[r][c] == '1' and bd[r + 1][c] == '0':
		res = [(r, c), (r, c + 1), (r + 1, c + 1)]
	elif bd[r][c] == '1' and bd[r + 1][c] == '1':
		res = [(r + 1, c), (r, c), (r, c + 1)]
	apply_change(bd, res)
	print_res(res)

def make_zero(bd, r, c, rsz, csz):
	if rsz == 2 and csz == 2:
		one = count_one(bd, r, c, 2, 2)
		if one == 0:
			return
		if one == 1 or one == 2:
			pick_one(bd, r, c, 1)
		elif one == 3 or one == 4:
			pick_one(bd, r, c, 3)
		make_zero(bd, r, c, 2, 2)
	elif rsz == 3 and csz == 2:
		one = count_one(bd, r, c, 1, 2)
		if one == 0:
			make_zero(bd, r + 1, c, 2, 2)
		else:
			remove_one(bd, r, c, 'top')
			make_zero(bd, r + 1, c, 2, 2)
	elif rsz == 2 and csz == 3:
		one = count_one(bd, r, c, 2, 1)
		if one == 0:
			make_zero(bd, r, c + 1, 2, 2)
		else:
			remove_one(bd, r, c, 'left')
			make_zero(bd, r, c + 1, 2, 2)
	else:
		one = count_one(bd, r, c, 1, 3)
		if one == 0:
			make_zero(bd, r + 1, c, 2, 3)
		elif bd[r][c] == '0':
			remove_one(bd, r, c + 1, 'top')
			make_zero(bd, r, c, 3, 3)
		else:
			remove_one(bd, r, c, 'top')
			make_zero(bd, r, c, 3, 3)
T = int(input())
for _ in range(T):
	(n, m) = map(int, input().split())
	bd = [list(input()) for _ in range(n)]
	for (i, j) in product(range(n // 2), range(m // 2)):
		(r, c) = (i * 2, j * 2)
		rsz = 3 if n % 2 and i == n // 2 - 1 else 2
		csz = 3 if m % 2 and j == m // 2 - 1 else 2
		make_zero(bd, r, c, rsz, csz)
	print(len(result))
	for res in result:
		ls = []
		for (u, v) in res:
			ls.append(u + 1)
			ls.append(v + 1)
		print(*ls)
	result.clear()


import sys
import bisect, string, math, time, functools, random, fractions
from heapq import heappush, heappop, heapify
from collections import deque, defaultdict, Counter
from itertools import permutations, combinations, groupby
rep = range
R = range

def Golf():
	(n, *t) = map(int, open(0).read().split())

def I():
	return int(input())

def S_():
	return input()

def IS():
	return input().split()

def LS():
	return [i for i in input().split()]

def MI():
	return map(int, input().split())

def LI():
	return [int(i) for i in input().split()]

def LI_():
	return [int(i) - 1 for i in input().split()]

def NI(n):
	return [int(input()) for i in range(n)]

def NI_(n):
	return [int(input()) - 1 for i in range(n)]

def NLI(n):
	return [[int(i) for i in input().split()] for i in range(n)]

def NLI_(n):
	return [[int(i) - 1 for i in input().split()] for i in range(n)]

def StoLI():
	return [ord(i) - 97 for i in input()]

def ItoS(n):
	return chr(n + 97)

def LtoS(ls):
	return ''.join([chr(i + 97) for i in ls])

def RA():
	return map(int, open(0).read().split())

def RLI(n=8, a=1, b=10):
	return [random.randint(a, b) for i in range(n)]

def RI(a=1, b=10):
	return random.randint(a, b)

def INP():
	N = 9
	n = random.randint(1, N)
	m = random.randint(1, n * n)
	A = [random.randint(1, n) for i in range(m)]
	B = [random.randint(1, n) for i in range(m)]
	G = [[] for i in range(n)]
	RG = [[] for i in range(n)]
	for i in range(m):
		(a, b) = (A[i] - 1, B[i] - 1)
		if a == b:
			continue
		G[a] += ((b, 1),)
		RG[b] += ((a, 1),)
	return (n, m, G, RG)

def Rtest(T):
	(case, err) = (0, 0)
	for i in range(T):
		inp = INP()
		a1 = naive(*inp)
		a2 = solve(*inp)
		if a1 == a2:
			print(inp)
			print('naive', a1)
			print('solve', a2)
			err += 1
		case += 1
	print('Tested', case, 'case with', err, 'errors')

def GI(V, E, ls=None, Directed=False, index=1):
	org_inp = []
	g = [[] for i in range(V)]
	FromStdin = True if ls == None else False
	for i in range(E):
		if FromStdin:
			inp = LI()
			org_inp.append(inp)
		else:
			inp = ls[i]
		if len(inp) == 2:
			(a, b) = inp
			c = 1
		else:
			(a, b, c) = inp
		if index == 1:
			a -= 1
			b -= 1
		aa = (a, c)
		bb = (b, c)
		g[a].append(bb)
		if not Directed:
			g[b].append(aa)
	return (g, org_inp)

def GGI(h, w, search=None, replacement_of_found='.', mp_def={'#': 1, '.': 0}, boundary=1):
	mp = [boundary] * (w + 2)
	found = {}
	for i in R(h):
		s = input()
		for char in search:
			if char in s:
				found[char] = (i + 1) * (w + 2) + s.index(char) + 1
				mp_def[char] = mp_def[replacement_of_found]
		mp += [boundary] + [mp_def[j] for j in s] + [boundary]
	mp += [boundary] * (w + 2)
	return (h + 2, w + 2, mp, found)

def TI(n):
	return GI(n, n - 1)

def accum(ls):
	rt = [0]
	for i in ls:
		rt += [rt[-1] + i]
	return rt

def bit_combination(n, base=2):
	rt = []
	for tb in R(base ** n):
		s = [tb // base ** bt % base for bt in R(n)]
		rt += [s]
	return rt

def gcd(x, y):
	if y == 0:
		return x
	if x % y == 0:
		return y
	while x % y != 0:
		(x, y) = (y, x % y)
	return y

def YN(x):
	print(['NO', 'YES'][x])

def Yn(x):
	print(['No', 'Yes'][x])

def show(*inp, end='\n'):
	if show_flg:
		print(*inp, end=end)
mo = 10 ** 9 + 7
inf = float('inf')
FourNb = [(-1, 0), (1, 0), (0, 1), (0, -1)]
EightNb = [(-1, 0), (1, 0), (0, 1), (0, -1), (1, 1), (-1, -1), (1, -1), (-1, 1)]
compas = dict(zip('WENS', FourNb))
cursol = dict(zip('LRUD', FourNb))
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
input = lambda : sys.stdin.readline().rstrip()

class Comb:

	def __init__(self, n, mo=10 ** 9 + 7):
		self.fac = [0] * (n + 1)
		self.inv = [1] * (n + 1)
		self.fac[0] = 1
		self.fact(n)
		for i in range(1, n + 1):
			self.fac[i] = i * self.fac[i - 1] % mo
			self.inv[n] *= i
			self.inv[n] %= mo
		self.inv[n] = pow(self.inv[n], mo - 2, mo)
		for i in range(1, n):
			self.inv[n - i] = self.inv[n - i + 1] * (n - i + 1) % mo
		return

	def fact(self, n):
		return self.fac[n]

	def invf(self, n):
		return self.inv[n]

	def comb(self, x, y):
		if y < 0 or y > x:
			return 0
		return self.fac[x] * self.inv[x - y] * self.inv[y] % mo
show_flg = False
show_flg = True
ans = 0

def solve(n, m, mp):
	cnt = 0
	rt = []
	for i in range(n - 2):
		for j in range(m):
			if mp[i][j] == 1:
				ans = [i, j, i + 1, j, i + 1, j + (-1 if j == m - 1 else 1)]
				rt += ans
				cnt += 1
				while ans:
					w = ans.pop()
					h = ans.pop()
					mp[h][w] = 1 - mp[h][w]
	for j in range(m - 2):
		if mp[n - 2][j] == 1 and mp[n - 1][j] == 1:
			ans = [n - 2, j, n - 1, j, n - 1, j + 1]
			rt += ans
			while ans:
				w = ans.pop()
				h = ans.pop()
				mp[h][w] = 1 - mp[h][w]
			cnt += 1
		elif mp[n - 2][j] == 1 and mp[n - 1][j] == 0:
			ans = [n - 2, j, n - 1, j + 1, n - 2, j + 1]
			rt += ans
			while ans:
				w = ans.pop()
				h = ans.pop()
				mp[h][w] = 1 - mp[h][w]
			cnt += 1
		elif mp[n - 2][j] == 0 and mp[n - 1][j] == 1:
			ans = [n - 2, j + 1, n - 1, j, n - 1, j + 1]
			rt += ans
			while ans:
				w = ans.pop()
				h = ans.pop()
				mp[h][w] = 1 - mp[h][w]
			cnt += 1
	lst = [[mp[i][j] for j in range(m - 2, m)] for i in range(n - 2, n)]
	lst2 = lst[0] + lst[1]
	ans = []
	if sum(lst2) == 4:
		ans = [n - 1, m - 1, n - 1, m - 2, n - 2, m - 1]
		rt += ans
		while ans:
			w = ans.pop()
			h = ans.pop()
			mp[h][w] = 1 - mp[h][w]
		lst = [[mp[i][j] for j in range(m - 2, m)] for i in range(n - 2, n)]
		lst2 = lst[0] + lst[1]
	if sum(lst2) == 0:
		pass
	elif sum(lst2) == 3:
		for i in range(n - 2, n):
			for j in range(m - 2, m):
				if mp[i][j] == 1:
					ans += [i, j]
		rt += ans
		while ans:
			w = ans.pop()
			h = ans.pop()
			mp[h][w] = 1 - mp[h][w]
		cnt += 1
	elif sum(lst2) <= 2:
		zero = []
		one = []
		for i in range(n - 2, n):
			for j in range(m - 2, m):
				if mp[i][j] == 0:
					zero += [i, j]
				else:
					one += [i, j]
		ans = zero[:4] + one[:2]
		rt += ans
		cnt += 1
		while ans:
			w = ans.pop()
			h = ans.pop()
			mp[h][w] = 1 - mp[h][w]
		if len(one) == 4:
			ans = zero[:4] + one[2:]
			rt += ans
			cnt += 1
			while ans:
				w = ans.pop()
				h = ans.pop()
				mp[h][w] = 1 - mp[h][w]
		else:
			zero = []
			one = []
			for i in range(n - 2, n):
				for j in range(m - 2, m):
					if mp[i][j] == 0:
						zero += [i, j]
					else:
						one += [i, j]
			ans = zero[:4] + one[:2]
			rt += ans
			cnt += 1
			while ans:
				w = ans.pop()
				h = ans.pop()
				mp[h][w] = 1 - mp[h][w]
			ans = zero[:4] + one[2:]
			rt += ans
			cnt += 1
			while ans:
				w = ans.pop()
				h = ans.pop()
				mp[h][w] = 1 - mp[h][w]
	return [rr + 1 for rr in rt]

def check(n, m, mp, rt):
	nn = len(rt) // 6
	ch = [i[:] for i in mp]
	for i in range(nn):
		(x, y, s, t, u, v) = [w - 1 for w in rt[i * 6:(i + 1) * 6]]
		if 0 <= x < n and 0 <= s < n and (0 <= u < n) and (0 <= y < m) and (0 <= t < m) and (0 <= v < m):
			pass
		else:
			return (False, 'not in area')
		if max(x, s, u) - min(x, s, u) > 1:
			return (False, 'not in square')
		if max(y, t, v) - min(y, t, v) > 1:
			return (False, 'not in square')
		if len(set([(x, y), (s, t), (u, v)])) < 3:
			return (False, 'same points')
		ch[x][y] = 1 - ch[x][y]
		ch[s][t] = 1 - ch[s][t]
		ch[u][v] = 1 - ch[u][v]
	tmp = 0
	for i in ch:
		tmp += sum(i)
	if tmp != 0:
		return (False, 'not 0', ch)
	return (True, 'ok', ch)

def sm(mp):
	show('-----------')
	for i in mp:
		show(*i)
T = I()
for _ in range(T):
	(n, m) = LI()
	mp = []
	for i in range(n):
		mp += ([int(i) for i in input()],)
	rt = solve(n, m, mp)
	nn = len(rt) // 6
	print(nn)
	for i in range(nn):
		print(*rt[i * 6:(i + 1) * 6])


import sys
reader = (s.rstrip() for s in sys.stdin)
input = reader.__next__
import math

def gift():
	for _ in range(t):
		(n, m) = list(map(int, input().split()))
		arys = []
		for i in range(n):
			tem = [int(x) for x in input()]
			arys.append(tem)
		ans = []
		irange = []
		if m == 2:
			j = 0
			for i in range(n - 1):
				x1 = arys[i][j]
				x2 = arys[i][j + 1]
				x3 = arys[i + 1][j]
				x4 = arys[i + 1][j + 1]
				if i != n - 2:
					diu = []
					if x1 + x2 != 0:
						if x1 == 1:
							diu.append(i)
							diu.append(j)
						if x2 == 1:
							diu.append(i)
							diu.append(j + 1)
						if x1 + x2 == 2:
							diu.append(i + 1)
							diu.append(j)
						else:
							diu.append(i + 1)
							diu.append(j)
							diu.append(i + 1)
							diu.append(j + 1)
						if len(diu) != 0:
							ans.append(diu)
							for z in range(3):
								x = diu[z * 2]
								y = diu[z * 2 + 1]
								arys[x][y] = 1 - arys[x][y]
				elif sum([x1, x2, x3, x4]) == 4:
					ans.append([i, j + 1, i + 1, j, i + 1, j + 1])
					ans.append([i, j, i, j + 1, i + 1, j])
					ans.append([i, j, i, j + 1, i + 1, j + 1])
					ans.append([i, j, i + 1, j, i + 1, j + 1])
					arys[i][j] = 0
					arys[i][j + 1] = 0
					arys[i + 1][j] = 0
					arys[i + 1][j + 1] = 0
				elif sum([x1, x2, x3, x4]) == 0:
					continue
				else:
					while sum([x1, x2, x3, x4]) != 0:
						x1 = arys[i][j]
						x2 = arys[i][j + 1]
						x3 = arys[i + 1][j]
						x4 = arys[i + 1][j + 1]
						diu = []
						if sum([x1, x2, x3, x4]) == 1:
							if x1 == 1:
								diu.extend([i, j])
							elif x2 == 1:
								diu.extend([i, j + 1])
							elif x3 == 1:
								diu.extend([i + 1, j])
							else:
								diu.extend([i + 1, j + 1])
							if x1 == 0:
								diu.extend([i, j])
							if x2 == 0:
								diu.extend([i, j + 1])
							if len(diu) == 4:
								if x3 == 0:
									diu.extend([i + 1, j])
								else:
									diu.extend([i + 1, j + 1])
							elif len(diu) == 2:
								diu.extend([i + 1, j])
								diu.extend([i + 1, j + 1])
						elif sum([x1, x2, x3, x4]) == 2:
							if x1 == 0:
								diu.extend([i, j])
							if x2 == 0:
								diu.extend([i, j + 1])
							if x3 == 0:
								diu.extend([i + 1, j])
							if x4 == 0:
								diu.extend([i + 1, j + 1])
							if x1 == 1:
								diu.extend([i, j])
							elif x2 == 1:
								diu.extend([i, j + 1])
							elif x3 == 1:
								diu.extend([i + 1, j])
							else:
								diu.extend([i + 1, j + 1])
						elif sum([x1, x2, x3, x4]) == 3:
							if x1 == 1:
								diu.extend([i, j])
							if x2 == 1:
								diu.extend([i, j + 1])
							if x3 == 1:
								diu.extend([i + 1, j])
							if x4 == 1:
								diu.extend([i + 1, j + 1])
						if len(diu) > 6:
							print(sum([x1, x2, x3, x4]))
							print(diu, 'lat')
						if len(diu) != 0:
							ans.append(diu)
							for z in range(3):
								x = diu[z * 2]
								y = diu[z * 2 + 1]
								arys[x][y] = 1 - arys[x][y]
		else:
			for kap in range(n // 2):
				irange.append(kap * 2)
			if n % 2:
				irange.append(n - 2)
			for i in irange:
				for j in range(m - 1):
					x1 = arys[i][j]
					x2 = arys[i][j + 1]
					x3 = arys[i + 1][j]
					x4 = arys[i + 1][j + 1]
					if j != m - 2:
						if sum([x1, x3]) == 0:
							continue
						else:
							diu = []
							if x1 == 1:
								diu.append(i)
								diu.append(j)
							if x3 == 1:
								diu.append(i + 1)
								diu.append(j)
							if len(diu) == 2:
								diu.append(i)
								diu.append(j + 1)
								diu.append(i + 1)
								diu.append(j + 1)
							else:
								if x2 == 1:
									diu.append(i)
									diu.append(j + 1)
								if len(diu) == 4:
									diu.append(i + 1)
									diu.append(j + 1)
							ans.append(diu)
							for z in range(3):
								x = diu[z * 2]
								y = diu[z * 2 + 1]
								arys[x][y] = 1 - arys[x][y]
					elif sum([x1, x2, x3, x4]) == 4:
						ans.append([i, j + 1, i + 1, j, i + 1, j + 1])
						ans.append([i, j, i, j + 1, i + 1, j])
						ans.append([i, j, i, j + 1, i + 1, j + 1])
						ans.append([i, j, i + 1, j, i + 1, j + 1])
						arys[i][j] = 0
						arys[i][j + 1] = 0
						arys[i + 1][j] = 0
						arys[i + 1][j + 1] = 0
					elif sum([x1, x2, x3, x4]) == 0:
						continue
					else:
						while sum([x1, x2, x3, x4]) != 0:
							x1 = arys[i][j]
							x2 = arys[i][j + 1]
							x3 = arys[i + 1][j]
							x4 = arys[i + 1][j + 1]
							diu = []
							if sum([x1, x2, x3, x4]) == 1:
								if x1 == 1:
									diu.extend([i, j])
								elif x2 == 1:
									diu.extend([i, j + 1])
								elif x3 == 1:
									diu.extend([i + 1, j])
								else:
									diu.extend([i + 1, j + 1])
								if x1 == 0:
									diu.extend([i, j])
								if x2 == 0:
									diu.extend([i, j + 1])
								if len(diu) == 4:
									if x3 == 0:
										diu.extend([i + 1, j])
									else:
										diu.extend([i + 1, j + 1])
								elif len(diu) == 2:
									diu.extend([i + 1, j])
									diu.extend([i + 1, j + 1])
							elif sum([x1, x2, x3, x4]) == 2:
								if x1 == 0:
									diu.extend([i, j])
								if x2 == 0:
									diu.extend([i, j + 1])
								if x3 == 0:
									diu.extend([i + 1, j])
								if x4 == 0:
									diu.extend([i + 1, j + 1])
								if x1 == 1:
									diu.extend([i, j])
								elif x2 == 1:
									diu.extend([i, j + 1])
								elif x3 == 1:
									diu.extend([i + 1, j])
								else:
									diu.extend([i + 1, j + 1])
							elif sum([x1, x2, x3, x4]) == 3:
								if x1 == 1:
									diu.extend([i, j])
								if x2 == 1:
									diu.extend([i, j + 1])
								if x3 == 1:
									diu.extend([i + 1, j])
								if x4 == 1:
									diu.extend([i + 1, j + 1])
							if len(diu) > 6:
								print(sum([x1, x2, x3, x4]))
								print(diu, 'lat')
							if len(diu) != 0:
								ans.append(diu)
								for z in range(3):
									x = diu[z * 2]
									y = diu[z * 2 + 1]
									arys[x][y] = 1 - arys[x][y]
		yield len(ans)
		for ele in ans:
			yield ' '.join([str(x + 1) for x in ele])
t = int(input())
ans = gift()
print(*ans, sep='\n')


import sys
import math
from collections import defaultdict, Counter
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
t = int(input())
for i in range(t):
	(n, m) = map(int, input().split())
	l = []
	for j in range(n):
		s = list(input())
		l.append(s)
	ans = []
	for j in range(n - 1):
		if j != n - 2:
			for k in range(m - 1):
				if k != m - 2:
					if l[j][k] == '1':
						cur1 = []
						cur1.extend([j + 1, k + 1])
						cur1.extend([j + 1, k + 2])
						cur1.extend([j + 2, k + 2])
						ans.append(cur1)
						l[j][k] = '0'
						if l[j][k + 1] == '1':
							l[j][k + 1] = '0'
						else:
							l[j][k + 1] = '1'
						if l[j + 1][k + 1] == '1':
							l[j + 1][k + 1] = '0'
						else:
							l[j + 1][k + 1] = '1'
				else:
					cur1 = []
					if l[j][k] == '1':
						cur1.extend([j + 1, k + 1])
						cur1.extend([j + 2, k + 2])
						if l[j + 1][k + 1] == '1':
							l[j + 1][k + 1] = '0'
						else:
							l[j + 1][k + 1] = '1'
						if l[j][k + 1] == '1':
							cur1.extend([j + 1, k + 2])
						else:
							cur1.extend([j + 2, k + 1])
							if l[j + 1][k] == '1':
								l[j + 1][k] = '0'
							else:
								l[j + 1][k] = '1'
						ans.append(cur1)
					elif l[j][k + 1] == '1':
						cur1.extend([j + 1, k + 2])
						cur1.extend([j + 2, k + 1])
						cur1.extend([j + 2, k + 2])
						if l[j + 1][k] == '1':
							l[j + 1][k] = '0'
						else:
							l[j + 1][k] = '1'
						if l[j + 1][k + 1] == '1':
							l[j + 1][k + 1] = '0'
						else:
							l[j + 1][k + 1] = '1'
						ans.append(cur1)
			continue
		for k in range(m - 1):
			cur = []
			if l[j][k] == '1':
				cur.extend([j + 1, k + 1])
			if l[j + 1][k] == '1':
				cur.extend([j + 2, k + 1])
			if k != m - 2:
				if len(cur) == 0:
					pass
				elif len(cur) == 4:
					cur.extend([j + 1, k + 2])
					if l[j][k + 1] == '1':
						l[j][k + 1] = '0'
					else:
						l[j][k + 1] = '1'
					ans.append(cur)
				else:
					cur.extend([j + 1, k + 2])
					cur.extend([j + 2, k + 2])
					if l[j][k + 1] == '1':
						l[j][k + 1] = '0'
					else:
						l[j][k + 1] = '1'
					if l[j + 1][k + 1] == '1':
						l[j + 1][k + 1] = '0'
					else:
						l[j + 1][k + 1] = '1'
					ans.append(cur)
				l[j][k] = '0'
				l[j + 1][k] = '0'
				continue
			if l[j][k + 1] == '1':
				cur.extend([j + 1, k + 2])
			if l[j + 1][k + 1] == '1':
				cur.extend([j + 2, k + 2])
			if len(cur) == 6:
				ans.append(cur)
			elif len(cur) == 2:
				cur1 = []
				if l[j][k] == '1' or l[j + 1][k] == '1':
					cur1.extend([j + 1, k + 1])
					cur1.extend([j + 2, k + 1])
					cur1.extend([j + 2, k + 2])
					ans.append(cur1)
					cur1 = []
					cur1.extend([j + 1, k + 1])
					cur1.extend([j + 2, k + 1])
					cur1.extend([j + 1, k + 2])
					ans.append(cur1)
					cur1 = []
					cur1.extend([j + 2, k + 2])
					cur1.extend([j + 1, k + 2])
					if l[j][k] == '1':
						cur1.extend([j + 1, k + 1])
					else:
						cur1.extend([j + 2, k + 1])
					ans.append(cur1)
				else:
					cur1.extend([j + 1, k + 1])
					cur1.extend([j + 1, k + 2])
					cur1.extend([j + 2, k + 2])
					ans.append(cur1)
					cur1 = []
					cur1.extend([j + 2, k + 1])
					cur1.extend([j + 2, k + 2])
					cur1.extend([j + 1, k + 2])
					ans.append(cur1)
					cur1 = []
					cur1.extend([j + 2, k + 1])
					cur1.extend([j + 1, k + 1])
					if l[j][k + 1] == '1':
						cur1.extend([j + 1, k + 2])
					else:
						cur1.extend([j + 2, k + 2])
					ans.append(cur1)
			elif len(cur) == 8:
				cur1 = []
				cur1.extend([j + 2, k + 2])
				cur1.extend([j + 1, k + 2])
				cur1.extend([j + 2, k + 1])
				ans.append(cur1)
				cur1 = []
				cur1.extend([j + 1, k + 1])
				cur1.extend([j + 2, k + 1])
				cur1.extend([j + 2, k + 2])
				ans.append(cur1)
				cur1 = []
				cur1.extend([j + 1, k + 1])
				cur1.extend([j + 2, k + 1])
				cur1.extend([j + 1, k + 2])
				ans.append(cur1)
				cur1 = []
				cur1.extend([j + 2, k + 2])
				cur1.extend([j + 1, k + 2])
				cur1.extend([j + 1, k + 1])
				ans.append(cur1)
			elif len(cur) == 4:
				if l[j][k] == '1':
					if l[j][k + 1] == '1':
						cur1 = []
						cur1.extend([j + 1, k + 1])
						cur1.extend([j + 2, k + 1])
						cur1.extend([j + 2, k + 2])
						ans.append(cur1)
						cur1 = []
						cur1.extend([j + 2, k + 1])
						cur1.extend([j + 2, k + 2])
						cur1.extend([j + 1, k + 2])
						ans.append(cur1)
					elif l[j + 1][k] == '1':
						cur1 = []
						cur1.extend([j + 1, k + 1])
						cur1.extend([j + 2, k + 2])
						cur1.extend([j + 1, k + 2])
						ans.append(cur1)
						cur1 = []
						cur1.extend([j + 2, k + 1])
						cur1.extend([j + 2, k + 2])
						cur1.extend([j + 1, k + 2])
						ans.append(cur1)
					else:
						cur1 = []
						cur1.extend([j + 2, k + 1])
						cur1.extend([j + 2, k + 2])
						cur1.extend([j + 1, k + 2])
						ans.append(cur1)
						cur1 = []
						cur1.extend([j + 1, k + 1])
						cur1.extend([j + 2, k + 1])
						cur1.extend([j + 1, k + 2])
						ans.append(cur1)
				elif l[j + 1][k + 1] == '1':
					if l[j][k + 1] == '1':
						cur1 = []
						cur1.extend([j + 1, k + 1])
						cur1.extend([j + 2, k + 1])
						cur1.extend([j + 1, k + 2])
						ans.append(cur1)
						cur1 = []
						cur1.extend([j + 2, k + 1])
						cur1.extend([j + 2, k + 2])
						cur1.extend([j + 1, k + 1])
						ans.append(cur1)
					else:
						cur1 = []
						cur1.extend([j + 1, k + 1])
						cur1.extend([j + 2, k + 1])
						cur1.extend([j + 1, k + 2])
						ans.append(cur1)
						cur1 = []
						cur1.extend([j + 2, k + 2])
						cur1.extend([j + 1, k + 2])
						cur1.extend([j + 1, k + 1])
						ans.append(cur1)
				else:
					cur1 = []
					cur1.extend([j + 1, k + 1])
					cur1.extend([j + 2, k + 2])
					cur1.extend([j + 1, k + 2])
					ans.append(cur1)
					cur1 = []
					cur1.extend([j + 2, k + 1])
					cur1.extend([j + 2, k + 2])
					cur1.extend([j + 1, k + 1])
					ans.append(cur1)
			l[j][k] = '0'
			l[j][k + 1] = '0'
			l[j + 1][k + 1] = '0'
			l[j + 1][k] = '0'
	print(len(ans))
	for i in ans:
		print(*i)


def read_ints():
	return list(map(int, input().split()))
d = {'0': '1', '1': '0'}

def change(rest, a, b, c):
	v = list(rest)
	for i in (a, b, c):
		v[i] = d[v[i]]
	return ''.join(v)

def get_moves(*args):
	result = []
	for i in args:
		result.extend([i % 2, i // 2])
	return [result]
d_rest = {'0000': []}
while len(d_rest) < 16:
	known = list(d_rest)
	for rest in known:
		new = change(rest, 0, 1, 2)
		if new not in d_rest:
			d_rest[new] = d_rest[rest] + get_moves(0, 1, 2)
		new = change(rest, 0, 1, 3)
		if new not in d_rest:
			d_rest[new] = d_rest[rest] + get_moves(0, 1, 3)
		new = change(rest, 0, 2, 3)
		if new not in d_rest:
			d_rest[new] = d_rest[rest] + get_moves(0, 2, 3)
		new = change(rest, 1, 2, 3)
		if new not in d_rest:
			d_rest[new] = d_rest[rest] + get_moves(1, 2, 3)

def remove_row(v):
	y = len(v) - 1
	row = v[-1]
	row1 = v[-2]
	result = []
	x = len(row) - 1
	while x > 0:
		if row[x] == '0':
			x -= 1
			continue
		if row[x - 1] == '1':
			result.append([x, y, x - 1, y, x, y - 1])
			row1[x] = d[row1[x]]
			x -= 2
			continue
		result.append([x, y, x, y - 1, x - 1, y - 1])
		row1[x] = d[row1[x]]
		row1[x - 1] = d[row1[x - 1]]
		x -= 2
	if x == 0 and row[0] == '1':
		result.append([0, y, 0, y - 1, 1, y - 1])
		row1[0] = d[row1[0]]
		row1[1] = d[row1[1]]
	del v[-1]
	return result

def remove_col(v):
	x = len(v[0]) - 1
	col = v[0][-1] + v[1][-1]
	del v[0][-1]
	del v[1][-1]
	if col == '00':
		return []
	if col == '01':
		v[0][-1] = d[v[0][-1]]
		v[1][-1] = d[v[1][-1]]
		return [[x, 1, x - 1, 0, x - 1, 1]]
	if col == '10':
		v[0][-1] = d[v[0][-1]]
		v[1][-1] = d[v[1][-1]]
		return [[x, 0, x - 1, 0, x - 1, 1]]
	v[0][-1] = d[v[0][-1]]
	return [[x, 0, x - 1, 0, x, 1]]
(t,) = read_ints()
for i in range(t):
	(n, m) = read_ints()
	values = [list(input()) for j in range(n)]
	moves = []
	while len(values) > 2:
		moves.extend(remove_row(values))
	while len(values[0]) > 2:
		moves.extend(remove_col(values))
	rest = ''.join(values[0] + values[1])
	moves.extend(d_rest[rest])
	print(len(moves))
	for (a, b, c, d0, e, f) in moves:
		print(*(b + 1, a + 1, d0 + 1, c + 1, f + 1, e + 1))


from __future__ import division, print_function
from fractions import Fraction
import sys
import os
from io import BytesIO, IOBase
from functools import cmp_to_key
from heapq import *
from math import gcd, factorial, floor, ceil, sqrt
from copy import deepcopy
from collections import deque
from bisect import bisect_left as bl
from bisect import bisect_right as br
from bisect import bisect
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
from types import GeneratorType

def iterative(f, stack=[]):

	def wrapped_func(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		to = f(*args, **kwargs)
		while True:
			if type(to) is GeneratorType:
				stack.append(to)
				to = next(to)
				continue
			stack.pop()
			if not stack:
				break
			to = stack[-1].send(to)
		return to
	return wrapped_func

def inp():
	return sys.stdin.readline().rstrip('\r\n')

def out(var):
	sys.stdout.write(str(var))

def lis():
	return list(map(int, inp().split()))

def stringlis():
	return list(map(str, inp().split()))

def sep():
	return map(int, inp().split())

def strsep():
	return map(str, inp().split())

def testcase(t):
	for pp in range(t):
		solve(pp)

def google(p):
	print('Case #' + str(p) + ': ', end='')

def lcm(a, b):
	return a * b // gcd(a, b)

def power(x, y, p):
	y %= p - 1
	res = 1
	x = x % p
	if x == 0:
		return 0
	while y > 0:
		if y & 1 == 1:
			res = res * x % p
		y = y >> 1
		x = x * x % p
	return res

def ncr(n, r):
	return factorial(n) // (factorial(r) * factorial(max(n - r, 1)))

def isPrime(n):
	if n <= 1:
		return False
	if n <= 3:
		return True
	if n % 2 == 0 or n % 3 == 0:
		return False
	i = 5
	while i * i <= n:
		if n % i == 0 or n % (i + 2) == 0:
			return False
		i = i + 6
	return True
inf = pow(10, 20)
mod = 10 ** 9 + 7
from random import randint

def solve(case):
	(n, m) = sep()
	g = []
	for i in range(n):
		temp = list(inp())
		for j in range(len(temp)):
			temp[j] = int(temp[j])
		g.append(temp)
	ans = []
	for i in range(n - 1):
		for j in range(m):
			if i == n - 2 and j == m - 1 or (i == n - 2 and j == m - 2):
				continue
			if g[i][j] == 1:
				if j != m - 1:
					ans.append((i, i + 1, i + 1, j, j, j + 1))
					g[i + 1][j] = 1 - g[i + 1][j]
					g[i + 1][j + 1] = 1 - g[i + 1][j + 1]
				else:
					ans.append((i, i + 1, i + 1, j, j, j - 1))
					g[i + 1][j] = 1 - g[i + 1][j]
					g[i + 1][j - 1] = 1 - g[i + 1][j - 1]
	i = n - 1
	for j in range(m - 2):
		if g[i][j] == 1:
			if g[i][j + 1] == 0:
				ans.append((i, i, i - 1, j, j + 1, j + 1))
				ans.append((i - 1, i, i, j + 1, j + 1, j + 2))
				g[i][j + 2] = 1 - g[i][j + 2]
			else:
				ans.append((i, i - 1, i - 1, j, j, j + 1))
				ans.append((i - 1, i - 1, i, j, j + 1, j + 1))
				g[i][j + 1] = 0
	if g[i - 1][m - 2] == 0:
		if g[i][m - 2] == 1 and g[i][m - 1] == 1:
			if g[i - 1][m - 1] == 1:
				ans.append((i - 1, i, i, m - 1, m - 1, m - 2))
			else:
				ans.append((i, i - 1, i - 1, m - 2, m - 2, m - 1))
				ans.append((i - 1, i - 1, i, m - 2, m - 1, m - 1))
		if g[i][m - 2] == 0 and g[i][m - 1] == 1:
			if g[i - 1][m - 1] == 1:
				ans.append((i - 1, i, i, m - 2, m - 2, m - 1))
				ans.append((i, i - 1, i - 1, m - 2, m - 2, m - 1))
			else:
				ans.append((i - 1, i, i, m - 2, m - 2, m - 1))
				ans.append((i - 1, i - 1, i, m - 2, m - 1, m - 1))
				ans.append((i - 1, i, i, m - 1, m - 1, m - 2))
		if g[i][m - 2] == 1 and g[i][m - 1] == 0:
			if g[i - 1][m - 1] == 1:
				ans.append((i - 1, i - 1, i, m - 2, m - 1, m - 1))
				ans.append((i - 1, i, i, m - 2, m - 2, m - 1))
			else:
				ans.append((i - 1, i, i, m - 2, m - 2, m - 1))
				ans.append((i - 1, i, i, m - 1, m - 1, m - 2))
				ans.append((i - 1, i - 1, i, m - 2, m - 1, m - 2))
		if g[i][m - 2] == 0 and g[i][m - 1] == 0 and (g[i - 1][m - 1] == 1):
			ans.append((i - 1, i - 1, i, m - 1, m - 2, m - 2))
			ans.append((i - 1, i - 1, i, m - 2, m - 1, m - 1))
			ans.append((i - 1, i, i, m - 1, m - 1, m - 2))
	else:
		if g[i][m - 2] == 1 and g[i][m - 1] == 1:
			if g[i - 1][m - 1] == 0:
				ans.append((i - 1, i, i, m - 2, m - 2, m - 1))
			else:
				ans.append((i - 1, i - 1, i, m - 2, m - 1, m - 1))
				ans.append((i, i - 1, i - 1, m - 2, m - 2, m - 1))
				ans.append((i - 1, i, i, m - 2, m - 2, m - 1))
				ans.append((i - 1, i, i, m - 1, m - 1, m - 2))
		if g[i][m - 2] == 0 and g[i][m - 1] == 0:
			if g[i - 1][m - 1] == 1:
				ans.append((i - 1, i, i, m - 2, m - 2, m - 1))
				ans.append((i - 1, i, i, m - 1, m - 1, m - 2))
			else:
				ans.append((i - 1, i, i, m - 2, m - 2, m - 1))
				ans.append((i, i - 1, i - 1, m - 2, m - 2, m - 1))
				ans.append((i - 1, i - 1, i, m - 2, m - 1, m - 1))
		if g[i][m - 2] == 1 and g[i][m - 1] == 0:
			if g[i - 1][m - 1] == 1:
				ans.append((i, i - 1, i - 1, m - 2, m - 2, m - 1))
			else:
				ans.append((i - 1, i - 1, i, m - 2, m - 1, m - 1))
				ans.append((i, i, i - 1, m - 2, m - 1, m - 1))
		if g[i][m - 2] == 0 and g[i][m - 1] == 1:
			if g[i - 1][m - 1] == 1:
				ans.append((i - 1, i - 1, i, m - 2, m - 1, m - 1))
			else:
				ans.append((i, i, i - 1, m - 2, m - 1, m - 1))
				ans.append((i, i - 1, i - 1, m - 2, m - 2, m - 1))
	print(len(ans))
	for i in range(len(ans)):
		print(ans[i][0] + 1, ans[i][3] + 1, ans[i][1] + 1, ans[i][4] + 1, ans[i][2] + 1, ans[i][5] + 1)
testcase(int(inp()))


from sys import stdin, stdout
from math import gcd, sqrt, factorial
from collections import deque, defaultdict
input = stdin.readline
R = lambda : map(int, input().split())
I = lambda : int(input())
S = lambda : input().rstrip('\n')
L = lambda : list(R())
P = lambda x: stdout.write(x)
lcm = lambda x, y: x * y // gcd(x, y)
hg = lambda x, y: (y + x - 1) // x * x
pw = lambda x: 0 if x == 1 else 1 + pw(x // 2)
chk = lambda x: chk(x // 2) if not x % 2 else True if x == 1 else False
sm = lambda x: (x ** 2 + x) // 2
N = 10 ** 9 + 7

def op1(x):
	ans = []
	cnt = 3
	for (i, j) in x[:2]:
		if a[i][j]:
			ans.extend([i + 1, j + 1])
			a[i][j] = 0
			cnt -= 1
	for (i, j) in x[2:]:
		if cnt:
			ans.extend([i + 1, j + 1])
			a[i][j] ^= 1
			cnt -= 1
	return ans

def op(x, flg):
	cnt = 3 - flg
	ans = []
	for (i, j) in x:
		if flg and a[i][j]:
			a[i][j] = 0
			ans.extend([i + 1, j + 1])
			flg -= 1
		elif cnt and (not a[i][j]):
			a[i][j] = 1
			ans.extend([i + 1, j + 1])
			cnt -= 1
	return ans
for i in range(I()):
	(n, m) = R()
	a = [list(map(int, S())) for i in range(n)]
	ans = []
	for i in range(n - 1):
		for j in range(m - 1):
			x = [(i, j), (i + 1, j), (i, j + 1), (i + 1, j + 1)]
			if j != m - 2 or i != n - 2:
				if j != m - 2:
					if sum([a[p][q] for (p, q) in x[:2]]):
						ans += (op1(x),)
				elif a[i][j] + a[i][j + 1]:
					ans += (op1([(i, j), (i, j + 1), (i + 1, j), (i + 1, j + 1)]),)
				continue
			else:
				cnt = sum([a[p][q] for (p, q) in x])
				if cnt == 0:
					continue
				if cnt == 4:
					ans += (op(x, 4),)
					cnt = 1
				if cnt == 1:
					ans += (op(x, 1),)
					cnt = 2
				if cnt == 2:
					ans += (op(x, 1),)
					cnt = 3
				if cnt == 3:
					ans += (op(x, 3),)
	print(len(ans))
	for i in ans:
		print(*i)


import io, os
from math import *

def move(i, j, n, m):
	if i < n - 1 and j < m - 1:
		return [(i + 1, j + 1, i + 2, j + 1, i + 1, j + 2), (i + 1, j + 1, i + 2, j + 1, i + 2, j + 2), (i + 1, j + 1, i + 2, j + 2, i + 1, j + 2)]
	elif i > 0 and j > 0:
		return [(i + 1, j + 1, i + 1, j, i, j + 1), (i, j, i + 1, j, i + 1, j + 1), (i, j, i + 1, j + 1, i, j + 1)]
	elif i == 0 and j == m - 1:
		return [(i + 1, j + 1, i + 2, j + 1, i + 2, j), (i + 1, j + 1, i + 1, j, i + 2, j), (i + 1, j + 1, i + 2, j + 1, i + 1, j)]
	else:
		return [(i + 1, j + 1, i, j + 1, i + 1, j + 2), (i + 1, j + 1, i + 1, j + 2, i, j + 2), (i + 1, j + 1, i, j + 1, i, j + 2)]

def fix_square(i, j, n, m, a):
	tl = int(a[i][j])
	tr = int(a[i][j + 1])
	bl = int(a[i + 1][j])
	br = int(a[i + 1][j + 1])
	total = tl + tr + bl + br
	if total == 0:
		return []
	elif total == 1:
		if tl == 1:
			return move(i, j, n, m)
		elif tr == 1:
			return move(i, j + 1, n, m)
		elif bl == 1:
			return move(i + 1, j, n, m)
		else:
			return move(i + 1, j + 1, n, m)
	elif total == 2:
		if tl == 1 and tr == 1:
			return [(i + 1, j + 1, i + 2, j + 1, i + 2, j + 2), (i + 2, j + 2, i + 2, j + 1, i + 1, j + 2)]
		elif tl == 1 and bl == 1:
			return [(i + 1, j + 1, i + 1, j + 2, i + 2, j + 2), (i + 2, j + 2, i + 2, j + 1, i + 1, j + 2)]
		elif tl == 1 and br == 1:
			return [(i + 1, j + 1, i + 2, j + 1, i + 1, j + 2), (i + 2, j + 2, i + 2, j + 1, i + 1, j + 2)]
		elif tr == 1 and bl == 1:
			return [(i + 1, j + 1, i + 1, j + 2, i + 2, j + 2), (i + 2, j + 2, i + 2, j + 1, i + 1, j + 1)]
		elif bl == 1 and br == 1:
			return [(i + 1, j + 1, i + 2, j + 1, i + 1, j + 2), (i + 2, j + 2, i + 1, j + 1, i + 1, j + 2)]
		else:
			return [(i + 1, j + 1, i + 2, j + 1, i + 1, j + 2), (i + 2, j + 2, i + 1, j + 1, i + 2, j + 1)]
	elif total == 3:
		if tl == 0:
			return [(i + 1, j + 2, i + 2, j + 1, i + 2, j + 2)]
		elif tr == 0:
			return [(i + 1, j + 1, i + 2, j + 1, i + 2, j + 2)]
		elif bl == 0:
			return [(i + 1, j + 2, i + 1, j + 1, i + 2, j + 2)]
		else:
			return [(i + 1, j + 2, i + 2, j + 1, i + 1, j + 1)]
	elif total == 4:
		return [(i + 1, j + 2, i + 2, j + 1, i + 2, j + 2), (i + 1, j + 1, i + 2, j + 1, i + 2, j + 2), (i + 1, j + 2, i + 1, j + 1, i + 2, j + 2), (i + 1, j + 2, i + 2, j + 1, i + 1, j + 1)]

def push_right(a, n, m):
	res = []
	for j in range(m - 2):
		for i in range(n):
			if a[i][j] == 1:
				if i > 0:
					res.append((i + 1, j + 1, i + 1, j + 2, i, j + 2))
					a[i][j] = 1 - a[i][j]
					a[i][j + 1] = 1 - a[i][j + 1]
					a[i - 1][j + 1] = 1 - a[i - 1][j + 1]
				else:
					res.append((i + 1, j + 1, i + 1, j + 2, i + 2, j + 2))
					a[i][j] = 1 - a[i][j]
					a[i][j + 1] = 1 - a[i][j + 1]
					a[i + 1][j + 1] = 1 - a[i + 1][j + 1]
	return (res, a)

def fix_corner(a, n, m):
	left = a[n - 1][m - 2]
	right = a[n - 1][m - 1]
	res = []
	if left == 1:
		res.append((n, m - 1, n - 1, m - 1, n - 1, m))
		a[n - 1][m - 2] = 1 - a[n - 1][m - 2]
		a[n - 2][m - 2] = 1 - a[n - 2][m - 2]
		a[n - 2][m - 1] = 1 - a[n - 2][m - 1]
	if right == 1:
		res.append((n, m, n - 1, m - 1, n - 1, m))
		a[n - 1][m - 1] = 1 - a[n - 1][m - 1]
		a[n - 2][m - 2] = 1 - a[n - 2][m - 2]
		a[n - 2][m - 1] = 1 - a[n - 2][m - 1]
	return (res, a)

def main():
	t = int(input())
	for _ in range(t):
		(n, m) = list(map(int, input().split()))
		a = [list(map(int, list(input()))) for _ in range(n)]
		(moves, a) = push_right(a, n, m)
		if n % 2 == 0:
			for i in range(0, n, 2):
				moves = moves + fix_square(i, m - 2, n, m, a)
		else:
			(moves2, a) = fix_corner(a, n, m)
			moves = moves + moves2
			for i in range(0, n - 1, 2):
				moves = moves + fix_square(i, m - 2, n, m, a)
		print(len(moves))
		for m in moves:
			print(str(m).replace(',', '').replace('(', '').replace(')', ''))
main()


import os
import sys
from io import BytesIO, IOBase
import threading
from bisect import bisect_right
from math import gcd, log
from collections import Counter, defaultdict
from pprint import pprint
import copy

def main(case_no):
	(n, m) = map(int, input().split())
	grid = []
	for i in range(n):
		grid.append([int(c) for c in input()])
	ans = []
	llt = copy.deepcopy(grid)
	for i in range(n - 2):
		for j in range(m):
			if grid[i][j] == 1:
				grid[i][j] = (grid[i][j] + 1) % 2
				grid[i + 1][j] = (grid[i + 1][j] + 1) % 2
				if j + 1 < m:
					grid[i][j + 1] = (grid[i][j + 1] + 1) % 2
					ans.append((i, j, i + 1, j, i, j + 1))
				else:
					grid[i + 1][j - 1] = (grid[i + 1][j - 1] + 1) % 2
					ans.append((i, j, i + 1, j, i + 1, j - 1))
	for i in range(m - 2):
		if grid[-2][i] == 1:
			grid[n - 2][i + 1] = (grid[n - 2][i + 1] + 1) % 2
			grid[n - 1][i + 1] = (grid[n - 1][i + 1] + 1) % 2
			grid[n - 2][i] = (grid[n - 2][i] + 1) % 2
			ans.append((n - 2, i + 1, n - 1, i + 1, n - 2, i))
		if grid[-1][i] == 1:
			grid[n - 2][i + 1] = (grid[n - 2][i + 1] + 1) % 2
			grid[n - 1][i + 1] = (grid[n - 1][i + 1] + 1) % 2
			grid[n - 1][i] = (grid[n - 1][i] + 1) % 2
			ans.append((n - 2, i + 1, n - 1, i + 1, n - 1, i))
	cc = [(n - 1, m - 1), (n - 1, m - 2), (n - 2, m - 1), (n - 2, m - 2)]
	ct = 0
	for (x, y) in cc:
		if grid[x][y] == 1:
			ct += 1
	if ct == 4:
		a = [n - 1, m - 1, n - 1, m - 2, n - 2, m - 1]
		ans.append(tuple(a))
		grid[a[0]][a[1]] = (grid[a[0]][a[1]] + 1) % 2
		grid[a[2]][a[3]] = (grid[a[2]][a[3]] + 1) % 2
		grid[a[4]][a[5]] = (grid[a[4]][a[5]] + 1) % 2
		ct = 1
	if ct == 1:
		a = []
		for (x, y) in cc:
			if grid[x][y] == 0:
				a.append(x)
				a.append(y)
				if len(a) == 4:
					break
		for (x, y) in cc:
			if grid[x][y] == 1:
				a.append(x)
				a.append(y)
				break
		ans.append(tuple(a))
		grid[a[0]][a[1]] = (grid[a[0]][a[1]] + 1) % 2
		grid[a[2]][a[3]] = (grid[a[2]][a[3]] + 1) % 2
		grid[a[4]][a[5]] = (grid[a[4]][a[5]] + 1) % 2
	if ct == 1 or ct == 2:
		a = []
		for (x, y) in cc:
			if grid[x][y] == 0:
				a.append(x)
				a.append(y)
		for (x, y) in cc:
			if grid[x][y] == 1:
				a.append(x)
				a.append(y)
				break
		grid[a[0]][a[1]] = (grid[a[0]][a[1]] + 1) % 2
		grid[a[2]][a[3]] = (grid[a[2]][a[3]] + 1) % 2
		grid[a[4]][a[5]] = (grid[a[4]][a[5]] + 1) % 2
		ans.append(a)
	if ct > 0:
		a = []
		for (x, y) in cc:
			if grid[x][y] == 1:
				a.append(x)
				a.append(y)
		ans.append(a)
		grid[a[0]][a[1]] = (grid[a[0]][a[1]] + 1) % 2
		grid[a[2]][a[3]] = (grid[a[2]][a[3]] + 1) % 2
		grid[a[4]][a[5]] = (grid[a[4]][a[5]] + 1) % 2
	for a in ans:
		llt[a[0]][a[1]] = (llt[a[0]][a[1]] + 1) % 2
		llt[a[2]][a[3]] = (llt[a[2]][a[3]] + 1) % 2
		llt[a[4]][a[5]] = (llt[a[4]][a[5]] + 1) % 2
	for i in range(n):
		for j in range(m):
			assert grid[i][j] == llt[i][j] == 0
	print(len(ans))
	assert len(ans) <= m * n
	for li in ans:
		print(*[i + 1 for i in li])
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
for _ in range(int(input())):
	main(_ + 1)


def main():
	from sys import stdin
	from random import randint, choice, shuffle
	from functools import lru_cache
	input = stdin.readline
	dx = [0, 0, 1, 1]
	dy = [0, 1, 0, 1]

	def g(i, j, a):
		return (i + dx[a] + 1, j + dy[a] + 1)

	def f(i, j, a, b, c):
		return (g(i, j, a), g(i, j, b), g(i, j, c))
	for _ in range(int(input())):
		ans = []
		(n, m) = map(int, input().split())
		s = [0] * n
		for i in range(n):
			s[i] = [int(c) for c in input()[:-1]]
		if n & 1 and m & 1 and s[n - 1][m - 1]:
			ans.append(f(n - 1 - 1, m - 1 - 1, 1, 2, 3))
			s[n - 1][m - 1] ^= 1
			s[n - 2][m - 1] ^= 1
			s[n - 1][m - 2] ^= 1
		if n & 1:
			for j in range(m - (m & 1)):
				if s[n - 1][j]:
					if not j:
						ans.append(f(n - 1 - 1, j, 0, 1, 2))
						s[n - 1][j] ^= 1
						s[n - 2][j] ^= 1
						s[n - 2][j + 1] ^= 1
					else:
						ans.append(f(n - 1 - 1, j - 1, 0, 1, 3))
						s[n - 1][j] ^= 1
						s[n - 2][j] ^= 1
						s[n - 2][j - 1] ^= 1
		if m & 1:
			for i in range(n - (n & 1)):
				if s[i][m - 1]:
					if not i:
						ans.append(f(i, m - 1 - 1, 0, 1, 2))
						s[i][m - 1] ^= 1
						s[i][m - 2] ^= 1
						s[i + 1][m - 2] ^= 1
					else:
						ans.append(f(i - 1, m - 1 - 1, 0, 2, 3))
						s[i][m - 1] ^= 1
						s[i][m - 2] ^= 1
						s[i - 1][m - 2] ^= 1
		for i in range(n - (n & 1)):
			for j in range(m - (m & 1)):
				if s[i][j] == 0:
					continue
				if 2 * (i & 1) + (j & 1) == 0:
					ans.append(f(i, j, 0, 1, 3))
					ans.append(f(i, j, 0, 2, 3))
					ans.append(f(i, j, 0, 1, 2))
				elif 2 * (i & 1) + (j & 1) == 1:
					ans.append(f(i, j - 1, 0, 1, 2))
					ans.append(f(i, j - 1, 1, 2, 3))
					ans.append(f(i, j - 1, 0, 1, 3))
				elif 2 * (i & 1) + (j & 1) == 2:
					ans.append(f(i - 1, j, 0, 1, 2))
					ans.append(f(i - 1, j, 1, 2, 3))
					ans.append(f(i - 1, j, 0, 2, 3))
				else:
					ans.append(f(i - 1, j - 1, 0, 1, 3))
					ans.append(f(i - 1, j - 1, 0, 2, 3))
					ans.append(f(i - 1, j - 1, 1, 2, 3))
		ans.sort()
		p = []
		c = 0
		ans1 = []
		for i in ans:
			if i == p:
				c += 1
			else:
				if c & 1:
					ans1.append(p)
				c = 1
				p = i
		if c & 1:
			ans1.append(p)
		print(len(ans1))
		for i in ans1:
			for j in i:
				print(*j, end=' ')
			print()
main()


for _ in range(int(input())):
	(n, m) = map(int, input().split())
	l = []
	for i in range(n):
		s = str(input())
		t = []
		for i in range(len(s)):
			t.append(int(s[i]))
		l.append(t)
	(lr, lc) = ([], [])
	for i in range(n - 2):
		for j in range(m):
			if j == m - 1:
				if l[i][j] == 1:
					lr.append(i)
					lc.append(j)
					l[i][j] = 0
					lr.append(i + 1)
					lc.append(j - 1)
					l[i + 1][j - 1] = 1 - l[i + 1][j - 1]
					lr.append(i + 1)
					lc.append(j)
					l[i + 1][j] = 1 - l[i + 1][j]
			elif l[i][j] == 1:
				lr.append(i)
				lc.append(j)
				l[i][j] = 0
				lr.append(i + 1)
				lc.append(j + 1)
				l[i + 1][j + 1] = 1 - l[i + 1][j + 1]
				lr.append(i + 1)
				lc.append(j)
				l[i + 1][j] = 1 - l[i + 1][j]
	if m % 2 != 0:
		if l[n - 2][m - 1] == 1:
			lr.append(n - 2)
			lc.append(m - 1)
			l[n - 2][m - 1] = 0
			lr.append(n - 2)
			lc.append(m - 2)
			l[n - 2][m - 2] = 1 - l[n - 2][m - 2]
			lr.append(n - 1)
			lc.append(m - 2)
			l[n - 1][m - 2] = 1 - l[n - 1][m - 2]
		if l[n - 1][m - 1] == 1:
			lr.append(n - 1)
			lc.append(m - 1)
			l[n - 1][m - 1] = 0
			lr.append(n - 2)
			lc.append(m - 2)
			l[n - 2][m - 2] = 1 - l[n - 2][m - 2]
			lr.append(n - 1)
			lc.append(m - 2)
			l[n - 1][m - 2] = 1 - l[n - 1][m - 2]
	i = n - 2
	for j in range(0, m - 1, 2):
		if l[i][j] == 1 and l[i + 1][j] == 1 and (l[i][j + 1] == 1) and (l[i + 1][j + 1] == 1):
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
		elif l[i][j] == 1 and l[i + 1][j] == 1 and (l[i + 1][j + 1] == 1):
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
		elif l[i][j] == 1 and l[i][j + 1] == 1 and (l[i + 1][j] == 1):
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
		elif l[i][j] == 1 and l[i][j + 1] == 1 and (l[i + 1][j + 1] == 1):
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
		elif l[i][j + 1] == 1 and l[i + 1][j] == 1 and (l[i + 1][j + 1] == 1):
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
		elif l[i][j] == 1 and l[i + 1][j] == 1:
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
		elif l[i][j] == 1 and l[i][j + 1] == 1:
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
		elif l[i][j + 1] == 1 and l[i + 1][j + 1] == 1:
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
		elif l[i + 1][j] == 1 and l[i + 1][j + 1] == 1:
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
		elif l[i][j] == 1 and l[i + 1][j + 1] == 1:
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
		elif l[i][j + 1] == 1 and l[i + 1][j] == 1:
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
		elif l[i][j] == 1:
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
		elif l[i][j + 1] == 1:
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
		elif l[i + 1][j] == 1:
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
		elif l[i + 1][j + 1] == 1:
			lr.append(i)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j)
			lr.append(i)
			lc.append(j + 1)
			lr.append(i + 1)
			lc.append(j + 1)
	print(len(lr) // 3)
	for i in range(0, len(lr), 3):
		print(lr[i] + 1, lc[i] + 1, lr[i + 1] + 1, lc[i + 1] + 1, lr[i + 2] + 1, lc[i + 2] + 1)


def inverse_1_2x2(i, j):
	res = []
	fstr = '{} {} {} {} {} {}'
	(step_i, step_j) = (1, 1)
	if i % 2 == 0:
		step_i = -1
	if j % 2 == 0:
		step_j = -1
	res.append(fstr.format(i + step_i, j + step_j, i + step_i, j, i, j))
	res.append(fstr.format(i + step_i, j, i, j, i, j + step_j))
	res.append(fstr.format(i, j, i, j + step_j, i + step_i, j + step_j))
	return res

def inverse_2_2x2(i, j, x1, x2):
	delta = (x2[0] - x1[0], x2[1] - x1[1])
	if delta[0] == 0 or delta[1] == 0:
		if x1[0] == i and x1[1] == j:
			x3 = (x1[0] + delta[1], x1[1] + delta[0])
		else:
			x3 = (x1[0] - delta[1], x1[1] - delta[0])
	else:
		x3 = (x1[0] + 1, x1[1])
	res = []
	fstr = '{} {} {} {} {} {}'
	res.append(fstr.format(*x1, *x2, *x3))
	res += inverse_1_2x2(*x3)
	return res

def inverce_cell(i, j, a):
	i -= 1
	j -= 1
	if a[i][j] == '1':
		a[i][j] = '0'
	else:
		a[i][j] = '1'

def process_last_row(a):
	res = []
	fstr = '{} {} {} {} {} {}'
	i = len(a)
	j = 1
	while j < len(a[-1]) - 1:
		if a[i - 1][j - 1] == '1':
			res.append(fstr.format(i, j, i - 1, j, i - 1, j + 1))
			inverce_cell(i - 1, j, a)
			inverce_cell(i - 1, j + 1, a)
		j += 1
	if a[i - 1][j - 1] == '1':
		if a[i - 1][j] == '1':
			res.append(fstr.format(i, j, i, j + 1, i - 1, j))
			inverce_cell(i - 1, j, a)
		else:
			res.append(fstr.format(i, j, i - 1, j, i - 1, j + 1))
			inverce_cell(i - 1, j, a)
			inverce_cell(i - 1, j + 1, a)
	elif a[i - 1][j] == '1':
		res.append(fstr.format(i, j + 1, i - 1, j + 1, i - 1, j))
		inverce_cell(i - 1, j + 1, a)
		inverce_cell(i - 1, j, a)
	return res

def process_last_col(a):
	res = []
	fstr = '{} {} {} {} {} {}'
	j = len(a[0])
	for i in range(1, len(a), 2):
		if a[i - 1][j - 1] == '1' and a[i][j - 1] == '1':
			res.append(fstr.format(i, j, i, j - 1, i + 1, j - 1))
			res.append(fstr.format(i, j - 1, i + 1, j - 1, i + 1, j))
		elif a[i - 1][j - 1] == '1':
			res.append(fstr.format(i, j, i, j - 1, i + 1, j - 1))
			inverce_cell(i, j - 1, a)
			inverce_cell(i + 1, j - 1, a)
		elif a[i][j - 1] == '1':
			res.append(fstr.format(i, j - 1, i + 1, j - 1, i + 1, j))
			inverce_cell(i, j - 1, a)
			inverce_cell(i + 1, j - 1, a)
	return res
for _ in range(int(input())):
	(n, m) = list(map(int, input().split(' ')))
	a = [list(input()) for _ in range(n)]
	out = []
	if n % 2 == 1:
		out += process_last_row(a)
	if m % 2 == 1:
		out += process_last_col(a)
	for blk_i in range(n // 2):
		i = 2 * blk_i + 1
		for blk_j in range(m // 2):
			j = 2 * blk_j + 1
			ones = [(i + ii, j + jj) for ii in range(2) for jj in range(2) if a[i + ii - 1][j + jj - 1] == '1']
			if len(ones) == 1:
				x1 = ones.pop()
				out += inverse_1_2x2(*x1)
			elif len(ones) == 2:
				out += inverse_2_2x2(i, j, *ones)
			elif len(ones) == 3:
				(x1, x2, x3) = ones
				out.append('{} {} {} {} {} {}'.format(*x1, *x2, *x3))
			elif len(ones) == 4:
				(x1, x2, x3, x4) = ones
				out.append('{} {} {} {} {} {}'.format(*x1, *x2, *x3))
				out += inverse_1_2x2(*x4)
	print(len(out))
	print('\n'.join(out))


import sys
import atexit
import io
import sys
_INPUT_LINES = sys.stdin.read().splitlines()
data = iter(_INPUT_LINES)

def input():
	return next(data)

def tprint(matrix):
	for row in matrix:
		print(*row)

def task_apply(matrix, op):
	for i in range(3):
		(y, x) = (op[2 * i], op[2 * i + 1])
		matrix[y][x] = 1 - matrix[y][x]
cache = [None] * 16

def sum_sq(matrix, i, j):
	return matrix[i][j] + matrix[i][j + 1] + matrix[i + 1][j] + matrix[i + 1][j + 1]

def get_k(matrix, i, j, k):
	indices = [(i, j), (i, j + 1), (i + 1, j), (i + 1, j + 1)]
	indices.sort(key=lambda o: matrix[o[0]][o[1]])
	indices = indices[-k:] + indices[:3 - k]
	return indices[0] + indices[1] + indices[2]
solver = {4: 3, 3: 3, 2: 1, 1: 1}

def solve_square(matrix, i, j):
	s = sum_sq(matrix, i, j)
	ans = []
	while s != 0:
		op = get_k(matrix, i, j, solver[s])
		task_apply(matrix, op)
		ans.append(op)
		s = sum_sq(matrix, i, j)
	return ans

def solve(matrix):
	ans = []
	n = len(matrix)
	m = len(matrix[0])
	if n % 2 == 1:
		for j in range(m):
			if matrix[-1][j] == 1:
				if j != 0:
					op = (n - 1, j, n - 2, j - 1, n - 2, j)
				else:
					op = (n - 1, j, n - 2, j, n - 2, j + 1)
				task_apply(matrix, op)
				ans.append(op)
	if m % 2 == 1:
		for i in range(n):
			if matrix[i][-1] == 1:
				if i != 0:
					op = (i, m - 1, i - 1, m - 2, i, m - 2)
				else:
					op = (i, m - 1, i, m - 2, i + 1, m - 2)
				task_apply(matrix, op)
				ans.append(op)
	for i in range(0, n, 2):
		for j in range(0, m, 2):
			if i + 1 < n and j + 1 < m:
				ops = solve_square(matrix, i, j)
				ans.extend(ops)
	return ans
ans = []
for _ in range(int(input())):
	(n, m) = map(int, input().split())
	matrix = []
	tprint(matrix)
	for _ in range(n):
		(*row,) = map(int, input())
		matrix.append(row)
	ans.append(solve(matrix))
output = []
for solution in ans:
	output.append(len(solution))
	output.append('\n'.join(('%s %s %s %s %s %s' % tuple((v + 1 for v in row)) for row in solution)))
print('\n'.join(map(str, output)))


def fn(ii, jj):
	if grid[ii][jj] == '0':
		grid[ii][jj] = '1'
	else:
		grid[ii][jj] = '0'

def solve(row):
	one = int(grid[row][c - 2]) + int(grid[row][c - 1]) + int(grid[row + 1][c - 2]) + int(grid[row + 1][c - 1])
	if one != 0:
		if one == 4:
			l.append([row + 1, c, row + 2, c - 1, row + 2, c])
			l.append([row + 1, c - 1, row + 2, c - 1, row + 2, c])
			l.append([row + 1, c - 1, row + 1, c, row + 2, c])
			l.append([row + 1, c - 1, row + 1, c, row + 2, c - 1])
		elif one == 3:
			ll = []
			if grid[row][c - 2] == '1':
				ll += [row + 1, c - 1]
			if grid[row][c - 1] == '1':
				ll += [row + 1, c]
			if grid[row + 1][c - 2] == '1':
				ll += [row + 2, c - 1]
			if grid[row + 1][c - 1] == '1':
				ll += [row + 2, c]
			l.append(ll)
		elif one == 2:
			if grid[row][c - 2] == '1' and grid[row][c - 1] == '1':
				l.append([row + 1, c, row + 2, c - 1, row + 2, c])
				l.append([row + 1, c - 1, row + 2, c - 1, row + 2, c])
			elif grid[row + 1][c - 2] == '1' and grid[row + 1][c - 1] == '1':
				l.append([row + 1, c - 1, row + 1, c, row + 2, c])
				l.append([row + 1, c - 1, row + 1, c, row + 2, c - 1])
			elif grid[row][c - 2] == '1' and grid[row + 1][c - 2] == '1':
				l.append([row + 1, c, row + 2, c - 1, row + 2, c])
				l.append([row + 1, c - 1, row + 1, c, row + 2, c])
			elif grid[row][c - 1] == '1' and grid[row + 1][c - 1] == '1':
				l.append([row + 1, c - 1, row + 2, c - 1, row + 2, c])
				l.append([row + 1, c - 1, row + 1, c, row + 2, c - 1])
			elif grid[row][c - 2] == '1' and grid[row + 1][c - 1] == '1':
				l.append([row + 1, c, row + 2, c - 1, row + 2, c])
				l.append([row + 1, c - 1, row + 1, c, row + 2, c - 1])
			else:
				l.append([row + 1, c - 1, row + 2, c - 1, row + 2, c])
				l.append([row + 1, c - 1, row + 1, c, row + 2, c])
		elif grid[row][c - 2] == '1':
			l.append([row + 1, c - 1, row + 2, c - 1, row + 2, c])
			l.append([row + 1, c - 1, row + 1, c, row + 2, c])
			l.append([row + 1, c - 1, row + 1, c, row + 2, c - 1])
		elif grid[row][c - 1] == '1':
			l.append([row + 1, c, row + 2, c - 1, row + 2, c])
			l.append([row + 1, c - 1, row + 1, c, row + 2, c])
			l.append([row + 1, c - 1, row + 1, c, row + 2, c - 1])
		elif grid[row + 1][c - 2] == '1':
			l.append([row + 1, c - 1, row + 1, c, row + 2, c - 1])
			l.append([row + 1, c, row + 2, c - 1, row + 2, c])
			l.append([row + 1, c - 1, row + 2, c - 1, row + 2, c])
		else:
			l.append([row + 1, c - 1, row + 1, c, row + 2, c])
			l.append([row + 1, c, row + 2, c - 1, row + 2, c])
			l.append([row + 1, c - 1, row + 2, c - 1, row + 2, c])
for _ in range(int(input())):
	(r, c) = map(int, input().split())
	grid = []
	for i in range(r):
		grid.append(list(input()))
	l = []
	for j in range(c - 2):
		for i in range(r):
			if grid[i][j] == '1':
				if i == r - 1:
					l.append([i + 1, j + 1, i + 1, j + 2, i, j + 2])
					fn(i - 1, j + 1)
				else:
					l.append([i + 1, j + 1, i + 1, j + 2, i + 2, j + 2])
					fn(i + 1, j + 1)
				fn(i, j)
				fn(i, j + 1)
	currow = 0
	if r % 2 != 0:
		if grid[0][c - 2] == '1':
			l.append([1, c - 1, 2, c - 1, 2, c])
			fn(0, c - 2)
			fn(1, c - 2)
			fn(1, c - 1)
		if grid[0][c - 1] == '1':
			l.append([1, c, 2, c - 1, 2, c])
			fn(0, c - 1)
			fn(1, c - 2)
			fn(1, c - 1)
		currow = 1
	while currow < r:
		solve(currow)
		currow += 2
	print(len(l))
	for i in l:
		print(*i)


t = int(input())
for _ in range(t):
	(n, m) = map(int, input().split())
	S = []
	for i in range(n):
		s = list(str(input()))
		s = [int(i) for i in s]
		S.append(s)
	ans = []
	for i in range(n - 1):
		for j in range(m - 1):
			if i == n - 2 and j == m - 2:
				X0 = []
				X1 = []
				if S[i][j] == 0:
					X0.append((i + 1, j + 1))
				else:
					X1.append((i + 1, j + 1))
				if S[i + 1][j] == 0:
					X0.append((i + 2, j + 1))
				else:
					X1.append((i + 2, j + 1))
				if S[i][j + 1] == 0:
					X0.append((i + 1, j + 2))
				else:
					X1.append((i + 1, j + 2))
				if S[i + 1][j + 1] == 0:
					X0.append((i + 2, j + 2))
				else:
					X1.append((i + 2, j + 2))
				if len(X1) == 1:
					temp = list(X0[0]) + list(X0[1]) + list(X1[0])
					ans.append(temp)
					temp = list(X0[0]) + list(X0[2]) + list(X1[0])
					ans.append(temp)
					temp = list(X0[1]) + list(X0[2]) + list(X1[0])
					ans.append(temp)
				elif len(X1) == 2:
					temp = list(X0[0]) + list(X0[1]) + list(X1[0])
					ans.append(temp)
					temp = list(X0[0]) + list(X0[1]) + list(X1[1])
					ans.append(temp)
				elif len(X1) == 3:
					temp = list(X1[0]) + list(X1[1]) + list(X1[2])
					ans.append(temp)
				elif len(X1) == 4:
					temp = list(X1[1]) + list(X1[2]) + list(X1[3])
					ans.append(temp)
					temp = list(X1[0]) + list(X1[1]) + list(X1[2])
					ans.append(temp)
					temp = list(X1[0]) + list(X1[1]) + list(X1[3])
					ans.append(temp)
					temp = list(X1[0]) + list(X1[2]) + list(X1[3])
					ans.append(temp)
				else:
					pass
				S[i][j] = 0
				S[i + 1][j] = 0
				S[i][j + 1] = 0
				S[i + 1][j + 1] = 0
			elif i == n - 2:
				if S[i][j] == 1 and S[i + 1][j] == 1:
					temp = [i + 1, j + 1, i + 2, j + 1, i + 1, j + 2]
					ans.append(temp)
					S[i][j] = 1 - S[i][j]
					S[i + 1][j] = 1 - S[i + 1][j]
					S[i][j + 1] = 1 - S[i][j + 1]
				elif S[i][j] == 1:
					temp = [i + 1, j + 1, i + 1, j + 2, i + 2, j + 2]
					ans.append(temp)
					S[i][j] = 1 - S[i][j]
					S[i][j + 1] = 1 - S[i][j + 1]
					S[i + 1][j + 1] = 1 - S[i + 1][j + 1]
				elif S[i + 1][j] == 1:
					temp = [i + 2, j + 1, i + 1, j + 2, i + 2, j + 2]
					ans.append(temp)
					S[i + 1][j] = 1 - S[i + 1][j]
					S[i][j + 1] = 1 - S[i][j + 1]
					S[i + 1][j + 1] = 1 - S[i + 1][j + 1]
				else:
					pass
			elif j == m - 2:
				if S[i][j] == 1 and S[i][j + 1] == 1:
					temp = [i + 1, j + 1, i + 1, j + 2, i + 2, j + 2]
					ans.append(temp)
					S[i][j] = 1 - S[i][j]
					S[i][j + 1] = 1 - S[i][j + 1]
					S[i + 1][j + 1] = 1 - S[i + 1][j + 1]
				elif S[i][j] == 1:
					temp = [i + 1, j + 1, i + 2, j + 1, i + 2, j + 2]
					ans.append(temp)
					S[i][j] = 1 - S[i][j]
					S[i + 1][j] = 1 - S[i + 1][j]
					S[i + 1][j + 1] = 1 - S[i + 1][j + 1]
				elif S[i][j + 1] == 1:
					temp = [i + 1, j + 2, i + 2, j + 1, i + 2, j + 2]
					ans.append(temp)
					S[i][j + 1] = 1 - S[i][j + 1]
					S[i + 1][j] = 1 - S[i + 1][j]
					S[i + 1][j + 1] = 1 - S[i + 1][j + 1]
				else:
					pass
			elif S[i][j] == 0:
				continue
			else:
				temp = [i + 1, j + 1, i + 1, j + 2, i + 2, j + 1]
				ans.append(temp)
				S[i][j] = 1 - S[i][j]
				S[i][j + 1] = 1 - S[i][j + 1]
				S[i + 1][j] = 1 - S[i + 1][j]
	print(len(ans))
	for i in range(len(ans)):
		print(*ans[i])


import sys, os, io
input = sys.stdin.readline
for _ in range(int(input())):
	(n, m) = [int(i) for i in input().split()]
	a = []
	for i in range(n):
		s = input().strip()
		a.append([int(i) for i in s])
	ans = []
	for i in range(n - 2):
		for j in range(0, m, 2):
			if j == m - 1:
				if a[i][j] == 1:
					ans.append([i + 1, j + 1, i + 2, j + 1, i + 2, j])
					a[i][j] ^= 1
					a[i + 1][j] ^= 1
					a[i + 1][j - 1] ^= 1
				continue
			if a[i][j] == 1 and a[i][j + 1] == 1:
				ans.append([i + 1, j + 1, i + 1, j + 2, i + 2, j + 1])
				a[i][j] ^= 1
				a[i][j + 1] ^= 1
				a[i + 1][j] ^= 1
				continue
			if a[i][j] == 1:
				ans.append([i + 1, j + 1, i + 2, j + 1, i + 2, j + 2])
				a[i][j] ^= 1
				a[i + 1][j] ^= 1
				a[i + 1][j + 1] ^= 1
				continue
			if a[i][j + 1] == 1:
				ans.append([i + 1, j + 2, i + 2, j + 1, i + 2, j + 2])
				a[i][j + 1] ^= 1
				a[i + 1][j] ^= 1
				a[i + 1][j + 1] ^= 1
				continue
	for j in range(m - 2):
		if a[n - 1][j] and a[n - 2][j]:
			ans.append([n, j + 1, n - 1, j + 1, n - 1, j + 2])
			a[n - 1][j] ^= 1
			a[n - 2][j] ^= 1
			a[n - 2][j + 1] ^= 1
			continue
		if a[n - 1][j]:
			ans.append([n, j + 1, n - 1, j + 2, n, j + 2])
			a[n - 1][j] ^= 1
			a[n - 2][j + 1] ^= 1
			a[n - 1][j + 1] ^= 1
			continue
		if a[n - 2][j]:
			ans.append([n - 1, j + 1, n - 1, j + 2, n, j + 2])
			a[n - 2][j] ^= 1
			a[n - 2][j + 1] ^= 1
			a[n - 1][j + 1] ^= 1
			continue
	if a[n - 2][m - 2] ^ a[n - 2][m - 1] ^ a[n - 1][m - 2]:
		ans.append([n - 1, m - 1, n - 1, m, n, m - 1])
	if a[n - 2][m - 2] ^ a[n - 1][m - 2] ^ a[n - 1][m - 1]:
		ans.append([n - 1, m - 1, n, m - 1, n, m])
	if a[n - 1][m - 2] ^ a[n - 2][m - 1] ^ a[n - 1][m - 1]:
		ans.append([n, m - 1, n - 1, m, n, m])
	if a[n - 2][m - 1] ^ a[n - 2][m - 2] ^ a[n - 1][m - 1]:
		ans.append([n - 1, m, n - 1, m - 1, n, m])
	print(len(ans))
	for i in ans:
		print(*i)


import math

def selectTiles(mepas, x, y):
	ans = []
	if mepas[x][y] == 1:
		ans.append(x + 1)
		ans.append(y + 1)
		mepas[x][y] = 0 if mepas[x][y] else 1
	if mepas[x][y + 1] == 1 or len(ans) < 2:
		ans.append(x + 1)
		ans.append(y + 2)
		mepas[x][y + 1] = 0 if mepas[x][y + 1] else 1
	if mepas[x + 1][y] == 1 or len(ans) < 4:
		ans.append(x + 2)
		ans.append(y + 1)
		mepas[x + 1][y] = 0 if mepas[x + 1][y] else 1
	if len(ans) < 6:
		ans.append(x + 2)
		ans.append(y + 2)
		mepas[x + 1][y + 1] = 0 if mepas[x + 1][y + 1] else 1
	return (mepas, tuple(ans))

def selectTiles2(mepas, x, y):
	ans = []
	if mepas[x][y] == 1:
		ans.append(x + 1)
		ans.append(y + 1)
		mepas[x][y] = 0 if mepas[x][y] else 1
	if mepas[x + 1][y] == 1 or len(ans) < 2:
		ans.append(x + 2)
		ans.append(y + 1)
		mepas[x + 1][y] = 0 if mepas[x + 1][y] else 1
	if mepas[x][y + 1] == 1 or len(ans) < 4:
		ans.append(x + 1)
		ans.append(y + 2)
		mepas[x][y + 1] = 0 if mepas[x][y + 1] else 1
	if len(ans) < 6:
		ans.append(x + 2)
		ans.append(y + 2)
		mepas[x + 1][y + 1] = 0 if mepas[x + 1][y + 1] else 1
	return (mepas, tuple(ans))

def countOnes(mepas, x, y):
	m = 0
	m += mepas[x][y]
	m += mepas[x + 1][y]
	m += mepas[x][y + 1]
	m += mepas[x + 1][y + 1]
	return m

def finishingTouch(mepas, x, y):
	ans = []
	c = countOnes(mepas, x, y)
	if c == 1:
		(mepas, a1) = oneLeft(mepas, x, y)
		(mepas, a2) = twoLeft(mepas, x, y)
		(mepas, a3) = selectTiles(mepas, x, y)
		ans.append(a1)
		ans.append(a2)
		ans.append(a3)
	elif c == 2:
		(mepas, a2) = twoLeft(mepas, x, y)
		(mepas, a3) = selectTiles(mepas, x, y)
		ans.append(a2)
		ans.append(a3)
	elif c == 3:
		(mepas, a3) = selectTiles(mepas, x, y)
		ans.append(a3)
	elif c == 4:
		(mepas, a0) = selectTiles(mepas, x, y)
		(mepas, a1) = oneLeft(mepas, x, y)
		(mepas, a2) = twoLeft(mepas, x, y)
		(mepas, a3) = selectTiles(mepas, x, y)
		ans.append(a0)
		ans.append(a1)
		ans.append(a2)
		ans.append(a3)
	return (mepas, ans)

def oneLeft(mepas, x, y):
	ones = 1
	zeros = 2
	ans = []
	for xx in range(2):
		for yy in range(2):
			if mepas[x + xx][y + yy] == 1 and ones > 0:
				ones -= 1
				ans.append(x + xx + 1)
				ans.append(y + yy + 1)
				mepas[x + xx][y + yy] = 0
			elif mepas[x + xx][y + yy] == 0 and zeros > 0:
				zeros -= 1
				ans.append(x + xx + 1)
				ans.append(y + yy + 1)
				mepas[x + xx][y + yy] = 1
	return (mepas, tuple(ans))

def twoLeft(mepas, x, y):
	ones = 1
	zeros = 2
	ans = []
	for xx in range(2):
		for yy in range(2):
			if mepas[x + xx][y + yy] == 1 and ones > 0:
				ones -= 1
				ans.append(x + xx + 1)
				ans.append(y + yy + 1)
				mepas[x + xx][y + yy] = 0
			elif mepas[x + xx][y + yy] == 0 and zeros > 0:
				zeros -= 1
				ans.append(x + xx + 1)
				ans.append(y + yy + 1)
				mepas[x + xx][y + yy] = 1
	return (mepas, tuple(ans))
T = int(input())
for t in range(T):
	(X, Y) = map(int, input().split())
	mepas = []
	ANS = []
	for x in range(X):
		y = [int(c) for c in input()]
		mepas.append(y)
	if X % 2 == 1:
		x = 0
		for y in range(Y - 1):
			if mepas[x][y] == 1 or (y == Y - 2 and mepas[x][y + 1] == 1):
				(mepas, temporary) = selectTiles(mepas, x, y)
				ANS.append(temporary)
	if Y % 2 == 1:
		y = 0
		for x in range(X - 1):
			if mepas[x][y] == 1 or (x == X - 2 and mepas[x + 1][y] == 1):
				(mepas, temporary) = selectTiles2(mepas, x, y)
				ANS.append(temporary)
	for x in range(0, X - 1, 2):
		x += X % 2
		for y in range(0, Y - 1, 2):
			y += Y % 2
			(mepas, temporary) = finishingTouch(mepas, x, y)
			ANS = ANS + temporary
	print(len(ANS))
	for a in ANS:
		print(*a)


def chgg(sttt):
	if sttt == '0':
		return '1'
	return '0'
T = int(input())
for _ in range(0, T):
	(n, m) = map(int, input().split())
	L = []
	for i in range(0, n):
		s = input()
		st = []
		for j in range(0, len(s)):
			st.append(s[j])
		L.append(st)
	ans = []
	for i in range(n - 1):
		for j in range(m - 1):
			if i == n - 2 and j == m - 2:
				for gg in range(4):
					ch = 0
					for e1 in range(2):
						for e2 in range(2):
							ch += int(L[i + e1][j + e2])
					if ch == 0:
						eee = 1
					elif ch == 1:
						h = []
						ct = 0
						for e1 in range(2):
							for e2 in range(2):
								if L[i + e1][j + e2] == '1':
									h.append(i + e1)
									h.append(j + e2)
									L[i + e1][j + e2] = '0'
								elif L[i + e1][j + e2] == '0' and ct < 2:
									ct += 1
									h.append(i + e1)
									h.append(j + e2)
									L[i + e1][j + e2] = '1'
						ans.append(h)
					elif ch == 2:
						h = []
						ct = 0
						for e1 in range(2):
							for e2 in range(2):
								if L[i + e1][j + e2] == '0':
									h.append(i + e1)
									h.append(j + e2)
									L[i + e1][j + e2] = '1'
								elif L[i + e1][j + e2] == '1' and ct < 1:
									ct += 1
									h.append(i + e1)
									h.append(j + e2)
									L[i + e1][j + e2] = '0'
						ans.append(h)
					elif ch == 3:
						h = []
						ct = 0
						for e1 in range(2):
							for e2 in range(2):
								if L[i + e1][j + e2] == '1':
									h.append(i + e1)
									h.append(j + e2)
									L[i + e1][j + e2] = '0'
						ans.append(h)
					elif ch == 4:
						h = []
						ct = 0
						for e1 in range(2):
							for e2 in range(2):
								if L[i + e1][j + e2] == '1' and ct < 3:
									ct += 1
									h.append(i + e1)
									h.append(j + e2)
									L[i + e1][j + e2] = '0'
						ans.append(h)
			elif i == n - 2:
				if L[i][j] == '1' and L[i + 1][j] == '1':
					ans.append([i, j, i + 1, j, i + 1, j + 1])
					L[i][j] = chgg(L[i][j])
					L[i + 1][j] = chgg(L[i + 1][j])
					L[i + 1][j + 1] = chgg(L[i + 1][j + 1])
				elif L[i][j] == '1' and L[i + 1][j] == '0':
					ans.append([i, j, i + 1, j + 1, i, j + 1])
					L[i][j] = chgg(L[i][j])
					L[i][j + 1] = chgg(L[i][j + 1])
					L[i + 1][j + 1] = chgg(L[i + 1][j + 1])
				elif L[i][j] == '0' and L[i + 1][j] == '1':
					ans.append([i + 1, j + 1, i, j + 1, i + 1, j])
					L[i][j + 1] = chgg(L[i][j + 1])
					L[i + 1][j] = chgg(L[i + 1][j])
					L[i + 1][j + 1] = chgg(L[i + 1][j + 1])
			elif L[i][j] == '1' and L[i][j + 1] == '1':
				ans.append([i, j, i, j + 1, i + 1, j])
				L[i][j + 1] = chgg(L[i][j + 1])
				L[i + 1][j] = chgg(L[i + 1][j])
				L[i][j] = chgg(L[i][j])
			elif L[i][j] == '1' and L[i][j + 1] == '0':
				ans.append([i, j, i + 1, j + 1, i + 1, j])
				L[i][j] = chgg(L[i][j])
				L[i + 1][j] = chgg(L[i + 1][j])
				L[i + 1][j + 1] = chgg(L[i + 1][j + 1])
			elif L[i][j] == '0' and L[i][j + 1] == '1':
				ans.append([i + 1, j + 1, i, j + 1, i + 1, j])
				L[i][j + 1] = chgg(L[i][j + 1])
				L[i + 1][j] = chgg(L[i + 1][j])
				L[i + 1][j + 1] = chgg(L[i + 1][j + 1])
	print(len(ans))
	for i in range(0, len(ans)):
		for j in range(0, len(ans[i])):
			ans[i][j] += 1
	for i in ans:
		print(*i)


for _ in range(int(input())):
	(n, m) = map(int, input().split())
	a = []
	li = []
	for __ in range(n):
		a.append(list(input()))
	for j in range(m - 2, 0, -1):
		for i in range(n - 1):
			if a[i][j + 1] == '1' and a[i + 1][j + 1] == '0':
				li.append([i + 1, j + 1 + 1, i + 1, j + 1, i + 1 + 1, j + 1])
				a[i][j + 1] = str(int(a[i][j + 1]) ^ 1)
				a[i][j] = str(int(a[i][j]) ^ 1)
				a[i + 1][j] = str(int(a[i + 1][j]) ^ 1)
			elif a[i][j + 1] == '0' and a[i + 1][j + 1] == '1':
				li.append([i + 1 + 1, j + 1 + 1, i + 1, j + 1, i + 1 + 1, j + 1])
				a[i + 1][j + 1] = str(int(a[i + 1][j + 1]) ^ 1)
				a[i][j] = str(int(a[i][j]) ^ 1)
				a[i + 1][j] = str(int(a[i + 1][j]) ^ 1)
			elif a[i][j + 1] == '1' and a[i + 1][j + 1] == '1':
				li.append([i + 1 + 1, j + 1 + 1, i + 1, j + 1 + 1, i + 1 + 1, j + 1])
				a[i + 1][j + 1] = str(int(a[i + 1][j + 1]) ^ 1)
				a[i][j + 1] = str(int(a[i][j + 1]) ^ 1)
				a[i + 1][j] = str(int(a[i + 1][j]) ^ 1)
	for i in range(n - 1):
		if a[i][0] == '1' and a[i][1] == '0':
			li.append([i + 1, 0 + 1, i + 1 + 1, 0 + 1, i + 1 + 1, 1 + 1])
			a[i][0] = str(int(a[i][0]) ^ 1)
			a[i + 1][0] = str(int(a[i + 1][0]) ^ 1)
			a[i + 1][1] = str(int(a[i + 1][1]) ^ 1)
		elif a[i][0] == '0' and a[i][1] == '1':
			li.append([i + 1, 1 + 1, i + 1 + 1, 0 + 1, i + 1 + 1, 1 + 1])
			a[i][1] = str(int(a[i][1]) ^ 1)
			a[i + 1][0] = str(int(a[i + 1][0]) ^ 1)
			a[i + 1][1] = str(int(a[i + 1][1]) ^ 1)
		elif a[i][0] == '1' and a[i][1] == '1':
			li.append([i + 1, 0 + 1, i + 1, 1 + 1, i + 1 + 1, 1 + 1])
			a[i][0] = str(int(a[i][0]) ^ 1)
			a[i][1] = str(int(a[i][1]) ^ 1)
			a[i + 1][1] = str(int(a[i + 1][1]) ^ 1)
	if a[n - 1][0] == '1' and a[n - 1][1] == '0':
		li.append([n - 1 + 1, 0 + 1, n - 2 + 1, 0 + 1, n - 2 + 1, 1 + 1])
		a[n - 1][0] = str(int(a[n - 1][0]) ^ 1)
		a[n - 2][0] = str(int(a[n - 2][0]) ^ 1)
		a[n - 2][1] = str(int(a[n - 2][1]) ^ 1)
		li.append([n - 2 + 1, 1 + 1, n - 1 + 1, 0 + 1, n - 1 + 1, 1 + 1])
		a[n - 2][1] = str(int(a[n - 2][1]) ^ 1)
		a[n - 1][0] = str(int(a[n - 1][0]) ^ 1)
		a[n - 1][1] = str(int(a[n - 1][1]) ^ 1)
		li.append([n - 2 + 1, 0 + 1, n - 1 + 1, 0 + 1, n - 1 + 1, 1 + 1])
		a[n - 2][0] = str(int(a[n - 2][0]) ^ 1)
		a[n - 1][0] = str(int(a[n - 1][0]) ^ 1)
		a[n - 1][1] = str(int(a[n - 1][1]) ^ 1)
	elif a[n - 1][0] == '0' and a[n - 1][1] == '1':
		li.append([n - 1 + 1, 1 + 1, n - 2 + 1, 0 + 1, n - 2 + 1, 1 + 1])
		a[n - 1][1] = str(int(a[n - 1][1]) ^ 1)
		a[n - 2][0] = str(int(a[n - 2][0]) ^ 1)
		a[n - 2][1] = str(int(a[n - 2][1]) ^ 1)
		li.append([n - 2 + 1, 1 + 1, n - 1 + 1, 0 + 1, n - 1 + 1, 1 + 1])
		a[n - 2][1] = str(int(a[n - 2][1]) ^ 1)
		a[n - 1][0] = str(int(a[n - 1][0]) ^ 1)
		a[n - 1][1] = str(int(a[n - 1][1]) ^ 1)
		li.append([n - 2 + 1, 0 + 1, n - 1 + 1, 0 + 1, n - 1 + 1, 1 + 1])
		a[n - 2][0] = str(int(a[n - 2][0]) ^ 1)
		a[n - 1][0] = str(int(a[n - 1][0]) ^ 1)
		a[n - 1][1] = str(int(a[n - 1][1]) ^ 1)
	elif a[n - 1][0] == '1' and a[n - 1][1] == '1':
		li.append([n - 1 + 1, 1 + 1, n - 2 + 1, 0 + 1, n - 2 + 1, 1 + 1])
		a[n - 1][1] = str(int(a[n - 1][1]) ^ 1)
		a[n - 2][0] = str(int(a[n - 2][0]) ^ 1)
		a[n - 2][1] = str(int(a[n - 2][1]) ^ 1)
		li.append([n - 1 + 1, 0 + 1, n - 2 + 1, 0 + 1, n - 2 + 1, 1 + 1])
		a[n - 1][0] = str(int(a[n - 1][0]) ^ 1)
		a[n - 2][0] = str(int(a[n - 2][0]) ^ 1)
		a[n - 2][1] = str(int(a[n - 2][1]) ^ 1)
	print(len(li))
	for i in li:
		print(*i, sep=' ')