A binary matrix is called good if every even length square sub-matrix has an odd number of ones. 

Given a binary matrix $a$ consisting of $n$ rows and $m$ columns, determine the minimum number of cells you need to change to make it good, or report that there is no way to make it good at all. 

All the terms above have their usual meanings — refer to the Notes section for their formal definitions. 


-----Input-----

The first line of input contains two integers $n$ and $m$ ($1 \leq n \leq m \leq 10^6$ and $n\cdot m \leq 10^6$)  — the number of rows and columns in $a$, respectively. 

The following $n$ lines each contain $m$ characters, each of which is one of 0 and 1. If the $j$-th character on the $i$-th line is 1, then $a_{i,j} = 1$. Similarly, if the $j$-th character on the $i$-th line is 0, then $a_{i,j} = 0$.


-----Output-----

Output the minimum number of cells you need to change to make $a$ good, or output $-1$ if it's not possible at all.


-----Examples-----
Input
3 3
101
001
110

Output
2
Input
7 15
000100001010010
100111010110001
101101111100100
010000111111010
111010010100001
000011001111101
111111011010011

Output
-1


-----Note-----

In the first case, changing $a_{1,1}$ to $0$ and $a_{2,2}$ to $1$ is enough. 

You can verify that there is no way to make the matrix in the second case good. 

Some definitions —   A binary matrix is one in which every element is either $1$ or $0$.  A sub-matrix is described by $4$ parameters — $r_1$, $r_2$, $c_1$, and $c_2$; here, $1 \leq r_1 \leq r_2 \leq n$ and $1 \leq c_1 \leq c_2 \leq m$.  This sub-matrix contains all elements $a_{i,j}$ that satisfy both $r_1 \leq i \leq r_2$ and $c_1 \leq j \leq c_2$.  A sub-matrix is, further, called an even length square if $r_2-r_1 = c_2-c_1$ and $r_2-r_1+1$ is divisible by $2$.

Difficulty: HARD
Tags: Bit manipulation

Constructive algorithms

Implementation

Complete search

Greedy algorithms

Dynamic programming
Skill types: Dynamic programming

Bit manipulation

Complete search

Greedy algorithms

Starter code:

Solutions:
(n, m) = [int(i) for i in input().split()]
matrix = ['' for i in range(n)]
for i in range(n):
	matrix[i] = input()
if n >= 4:
	print(-1)
elif n == 1:
	print(0)
elif n == 2:
	ps = 0
	ptl = 0
	for i in range(m):
		if (int(matrix[0][i]) + int(matrix[1][i])) % 2 == i % 2:
			ps += 1
		else:
			ptl += 1
	print(min([ps, ptl]))
else:
	ans = [[m, m], [m, m]]
	for i in range(m):
		up = (int(matrix[0][i]) + int(matrix[1][i])) % 2
		down = (int(matrix[1][i]) + int(matrix[2][i])) % 2
		if down == i % 2:
			if up == i % 2:
				ans[0][0] -= 1
			else:
				ans[0][1] -= 1
		elif up == i % 2:
			ans[1][0] -= 1
		else:
			ans[1][1] -= 1
	final = min([min(ans[0]), min(ans[1])])
	print(final)


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())

def print_list(l):
	print(' '.join(map(str, l)))
(n, m) = RL()
grid = []
for _ in range(n):
	grid.append(input())
data = []
if min(m, n) > 3:
	print(-1)
elif min(m, n) == 1:
	print(0)
else:
	for i in range(m):
		if n == 2:
			data.append(int(grid[0][i] + grid[1][i], base=2))
		else:
			data.append(int(grid[0][i] + grid[1][i] + grid[2][i], base=2))
	dic = {}
	dbit = {}
	dbit[0] = 0
	dbit[1] = 1
	dbit[2] = 1
	dbit[3] = 2
	dbit[4] = 1
	dbit[5] = 2
	dbit[6] = 2
	dbit[7] = 3
	if n == 2:
		dic[0] = [1, 2]
		dic[1] = [0, 3]
		dic[2] = [0, 3]
		dic[3] = [1, 2]
	else:
		dic[0] = [2, 5]
		dic[1] = [4, 3]
		dic[2] = [0, 7]
		dic[3] = [1, 6]
		dic[4] = [1, 6]
		dic[5] = [0, 7]
		dic[6] = [3, 4]
		dic[7] = [2, 5]
	dp = [[0] * 2 ** n for _ in range(m)]
	for coin in range(2 ** n):
		dp[0][coin] = dbit[data[0] ^ coin]
	for i in range(1, m):
		for coin in range(2 ** n):
			dp[i][coin] = min(dp[i - 1][dic[coin][0]], dp[i - 1][dic[coin][1]]) + dbit[data[i] ^ coin]
	print(min(dp[-1]))


raw = input()
(n, m) = map(int, raw.split(' '))
mx = []
for ri in range(n):
	mx += [input()]
if n >= 4:
	print(-1)
if n == 1:
	print(0)
if n == 2:
	p = m // 2
	s = 'AB' * (p + 2)
	s1 = s[:m]
	s2 = s[1:m + 1]
	(r1, r2) = (0, 0)
	for i in range(m):
		o1 = int(mx[0][i] != mx[1][i])
		letter = 'AB'[o1]
		if letter != s1[i]:
			r1 += 1
		if letter != s2[i]:
			r2 += 1
	print(min(r1, r2))
if n == 3:
	p = m // 2
	s = 'AD' * (p + 2)
	s1 = s[:m]
	s2 = s[1:m + 1]
	s = 'BC' * (p + 2)
	s3 = s[:m]
	s4 = s[1:m + 1]
	(r1, r2, r3, r4) = (0, 0, 0, 0)
	for i in range(m):
		o1 = int(mx[0][i] != mx[1][i])
		o2 = int(mx[1][i] != mx[2][i])
		letter = 'ABCD'[o1 * 2 + o2]
		if letter != s1[i]:
			r1 += 1
		if letter != s2[i]:
			r2 += 1
		if letter != s3[i]:
			r3 += 1
		if letter != s4[i]:
			r4 += 1
	rez = min(min(r1, r2), min(r3, r4))
	print(rez)


import math
import sys
input = sys.stdin.readline
(n, m) = [int(_) for _ in input().split()]
M = []
for i in range(n):
	row = input()[:-1]
	M.append(row)
if n >= 4 and m >= 4:
	print(-1)
elif n == 1 or m == 1:
	print(0)
else:
	if n <= m:
		R = [[True] * (m - 1) for _ in range(2)]
		for i in range(n - 1):
			for j in range(m - 1):
				count = 0
				if M[i][j] == '1':
					count += 1
				if M[i + 1][j + 1] == '1':
					count += 1
				if M[i + 1][j] == '1':
					count += 1
				if M[i][j + 1] == '1':
					count += 1
				if not count % 2:
					R[i][j] = False
	else:
		R = [[True] * (n - 1) for _ in range(2)]
		for i in range(m - 1):
			for j in range(n - 1):
				count = 0
				if M[j][i] == '1':
					count += 1
				if M[j + 1][i + 1] == '1':
					count += 1
				if M[j + 1][i] == '1':
					count += 1
				if M[j][i + 1] == '1':
					count += 1
				if not count % 2:
					R[i][j] = False
	mnm = max(n, m)
	dp_all_good = [math.inf] * mnm
	dp_all_bad = [math.inf] * mnm
	dp_top_bad = [math.inf] * mnm
	dp_bot_bad = [math.inf] * mnm
	dp_all_good[0] = 0
	dp_all_bad[0] = 0
	dp_top_bad[0] = 0
	dp_bot_bad[0] = 0
	for i in range(1, len(R[0]) + 1):
		if R[0][i - 1] and R[1][i - 1]:
			dp_all_good[i] = min(dp_all_good[i], dp_all_good[i - 1])
			dp_all_bad[i] = min(dp_all_bad[i], dp_all_bad[i - 1] + 1)
			dp_top_bad[i] = min(dp_top_bad[i], dp_top_bad[i - 1] + 1)
			dp_bot_bad[i] = min(dp_bot_bad[i], dp_bot_bad[i - 1] + 1)
		if not R[0][i - 1] and (not R[1][i - 1]):
			dp_all_good[i] = min(dp_all_good[i], dp_all_bad[i - 1] + 1)
			dp_all_bad[i] = min(dp_all_bad[i], dp_all_good[i - 1])
			dp_top_bad[i] = min(dp_top_bad[i], dp_bot_bad[i - 1] + 1)
			dp_bot_bad[i] = min(dp_bot_bad[i], dp_top_bad[i - 1] + 1)
		if R[0][i - 1] and (not R[1][i - 1]):
			dp_all_good[i] = min(dp_all_good[i], dp_bot_bad[i - 1] + 1)
			dp_all_bad[i] = min(dp_all_bad[i], dp_top_bad[i - 1] + 1)
			dp_top_bad[i] = min(dp_top_bad[i], dp_all_bad[i - 1] + 1)
			dp_bot_bad[i] = min(dp_bot_bad[i], dp_all_good[i - 1])
		if not R[0][i - 1] and R[1][i - 1]:
			dp_all_good[i] = min(dp_all_good[i], dp_top_bad[i - 1] + 1)
			dp_all_bad[i] = min(dp_all_bad[i], dp_bot_bad[i - 1] + 1)
			dp_top_bad[i] = min(dp_top_bad[i], dp_all_good[i - 1])
			dp_bot_bad[i] = min(dp_bot_bad[i], dp_all_bad[i - 1] + 1)
	print(min(dp_all_good[mnm - 1], dp_all_bad[mnm - 1] + 1, dp_bot_bad[mnm - 1] + 1, dp_top_bad[mnm - 1] + 1))


import itertools
(n, m) = map(int, input().split())
rows = []
for _ in range(n):
	rows.append(list(map(int, input())))
if m >= 4 and n >= 4:
	print(-1)
	exit()
if m == 1 or n == 1:
	print(0)
	exit()
if n == 2 or m == 2:
	if n == 2:
		pars = [(rows[0][i] + rows[1][i]) % 2 for i in range(m)]
	else:
		pars = [(rows[i][0] + rows[i][1]) % 2 for i in range(n)]
	best = 10 ** 8
	for to_match in [itertools.cycle([0, 1]), itertools.cycle([1, 0])]:
		cost = 0
		for (x, y) in zip(pars, to_match):
			cost += abs(x - y)
		best = min(best, cost)
	print(best)
	exit()
best = 10 ** 8
if n == 3:
	vals = [((rows[0][i] + rows[1][i]) % 2, (rows[1][i] + rows[2][i]) % 2) for i in range(m)]
else:
	vals = [((rows[i][0] + rows[i][1]) % 2, (rows[i][1] + rows[i][2]) % 2) for i in range(n)]
for (up, down) in itertools.product([0, 1], repeat=2):
	cost = 0
	for (cur_up, cur_down) in vals:
		up = 1 - up
		down = 1 - down
		diff = abs(cur_up - up) + abs(cur_down - down)
		if diff == 2:
			diff = 1
		cost += diff
	best = min(best, cost)
print(best)


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')
from math import gcd, ceil

def prod(a, mod=10 ** 9 + 7):
	ans = 1
	for each in a:
		ans = ans * each % mod
	return ans

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

def binary(x, length=16):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y
for _ in range(int(input()) if not True else 1):
	(n, m) = map(int, input().split())
	a = []
	for i in range(n):
		a += [list(map(int, input()))]
	if n >= 4:
		print(-1)
		continue
	if n == 1:
		print(0)
		continue
	if n == 2:
		ans = 0
		for i in range(m):
			if (a[0][i] + a[1][i]) % 2 == i % 2:
				ans += 1
		print(min(ans, m - ans))
		continue
	if n == 3:
		ans = [0] * 4
		for i in range(m):
			ans[2 * int((a[0][i] + a[1][i]) % 2 == i % 2) + int((a[1][i] + a[2][i]) % 2 == i % 2)] += 1
		print(m - max(ans))


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
A = [list(map(int, list(input().strip()))) for i in range(n)]
if n >= 4 and m >= 4:
	print(-1)
	sys.exit()
if n == 1 or m == 1:
	print(0)
	sys.exit()
if m == 2 or m == 3:
	B = [[0] * n for i in range(m)]
	for i in range(m):
		for j in range(n):
			B[i][j] = A[j][i]
	(n, m) = (m, n)
	A = B
if n == 2:
	DP0 = [1 << 30] * m
	DP1 = [1 << 30] * m
	if (A[0][0] + A[1][0]) % 2 == 0:
		DP0[0] = 0
		DP1[0] = 1
	else:
		DP0[0] = 1
		DP1[0] = 0
	for i in range(1, m):
		if (A[0][i] + A[1][i]) % 2 == 0:
			DP0[i] = DP1[i - 1]
			DP1[i] = DP0[i - 1] + 1
		else:
			DP0[i] = DP1[i - 1] + 1
			DP1[i] = DP0[i - 1]
	print(min(DP0[-1], DP1[-1]))
if n == 3:
	DP0 = [1 << 30] * m
	DP1 = [1 << 30] * m
	DP2 = [1 << 30] * m
	DP3 = [1 << 30] * m
	if (A[0][0] + A[1][0]) % 2 == 0 and (A[1][0] + A[2][0]) % 2 == 0:
		DP0[0] = 0
		DP1[0] = 1
		DP2[0] = 1
		DP3[0] = 1
	elif (A[0][0] + A[1][0]) % 2 == 0 and (A[1][0] + A[2][0]) % 2 == 1:
		DP0[0] = 1
		DP1[0] = 0
		DP2[0] = 1
		DP3[0] = 1
	elif (A[0][0] + A[1][0]) % 2 == 1 and (A[1][0] + A[2][0]) % 2 == 0:
		DP0[0] = 1
		DP1[0] = 1
		DP2[0] = 0
		DP3[0] = 1
	elif (A[0][0] + A[1][0]) % 2 == 1 and (A[1][0] + A[2][0]) % 2 == 1:
		DP0[0] = 1
		DP1[0] = 1
		DP2[0] = 1
		DP3[0] = 0
	for i in range(1, m):
		if (A[0][i] + A[1][i]) % 2 == 0 and (A[1][i] + A[2][i]) % 2 == 0:
			DP0[i] = DP3[i - 1]
			DP1[i] = DP2[i - 1] + 1
			DP2[i] = DP1[i - 1] + 1
			DP3[i] = DP0[i - 1] + 1
		elif (A[0][i] + A[1][i]) % 2 == 0 and (A[1][i] + A[2][i]) % 2 == 1:
			DP0[i] = DP3[i - 1] + 1
			DP1[i] = DP2[i - 1]
			DP2[i] = DP1[i - 1] + 1
			DP3[i] = DP0[i - 1] + 1
		elif (A[0][i] + A[1][i]) % 2 == 1 and (A[1][i] + A[2][i]) % 2 == 0:
			DP0[i] = DP3[i - 1] + 1
			DP1[i] = DP2[i - 1] + 1
			DP2[i] = DP1[i - 1]
			DP3[i] = DP0[i - 1] + 1
		elif (A[0][i] + A[1][i]) % 2 == 1 and (A[1][i] + A[2][i]) % 2 == 1:
			DP0[i] = DP3[i - 1] + 1
			DP1[i] = DP2[i - 1] + 1
			DP2[i] = DP1[i - 1] + 1
			DP3[i] = DP0[i - 1]
	print(min(DP0[-1], DP1[-1], DP2[-1], DP3[-1]))


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 j in range(b)] for i in range(a)]

def list4d(a, b, c, d, e):
	return [[[[e] * d for j in range(c)] for j 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

def popcount(x):
	x -= x >> 1 & 85
	x = (x & 51) + (x >> 2 & 51)
	x = x + (x >> 4) & 15
	return x & 15
(H, W) = MAP()
grid = [[]] * H
for i in range(H):
	grid[i] = list(map(int, input()))
if H >= 4 and W >= 4:
	print(-1)
	exit()
if H == 1 or W == 1:
	print(0)
	exit()
if W > H:
	grid = list(zip(*grid))
	(H, W) = (W, H)
cur = 0
dp = list2d(H, 2 ** W, INF)
for j in range(W):
	if grid[0][j]:
		k = W - j - 1
		cur += 1 << k
if W == 2:
	for nxt in range(2 ** W):
		dp[0][nxt] = popcount(cur ^ nxt)
	for i in range(1, H):
		cur = 0
		for j in range(W):
			if grid[i][j]:
				k = W - j - 1
				cur += 1 << k
		for k in range(2 ** W):
			if k in (1, 2):
				dp[i][0] = min(dp[i][0], dp[i - 1][k] + popcount(cur ^ 0))
				dp[i][3] = min(dp[i][3], dp[i - 1][k] + popcount(cur ^ 3))
			else:
				dp[i][2] = min(dp[i][2], dp[i - 1][k] + popcount(cur ^ 2))
				dp[i][1] = min(dp[i][1], dp[i - 1][k] + popcount(cur ^ 1))
else:
	for nxt in range(2 ** W):
		dp[0][nxt] = popcount(cur ^ nxt)
	for i in range(1, H):
		cur = 0
		for j in range(W):
			if grid[i][j]:
				k = W - j - 1
				cur += 1 << k
		dp[i][0] = min(dp[i][0], dp[i - 1][5] + popcount(cur ^ 0))
		dp[i][0] = min(dp[i][0], dp[i - 1][2] + popcount(cur ^ 0))
		dp[i][1] = min(dp[i][1], dp[i - 1][3] + popcount(cur ^ 1))
		dp[i][1] = min(dp[i][1], dp[i - 1][4] + popcount(cur ^ 1))
		dp[i][2] = min(dp[i][2], dp[i - 1][7] + popcount(cur ^ 2))
		dp[i][2] = min(dp[i][2], dp[i - 1][0] + popcount(cur ^ 2))
		dp[i][3] = min(dp[i][3], dp[i - 1][6] + popcount(cur ^ 3))
		dp[i][3] = min(dp[i][3], dp[i - 1][1] + popcount(cur ^ 3))
		dp[i][4] = min(dp[i][4], dp[i - 1][1] + popcount(cur ^ 4))
		dp[i][4] = min(dp[i][4], dp[i - 1][6] + popcount(cur ^ 4))
		dp[i][5] = min(dp[i][5], dp[i - 1][7] + popcount(cur ^ 5))
		dp[i][5] = min(dp[i][5], dp[i - 1][0] + popcount(cur ^ 5))
		dp[i][6] = min(dp[i][6], dp[i - 1][4] + popcount(cur ^ 6))
		dp[i][6] = min(dp[i][6], dp[i - 1][3] + popcount(cur ^ 6))
		dp[i][7] = min(dp[i][7], dp[i - 1][5] + popcount(cur ^ 7))
		dp[i][7] = min(dp[i][7], dp[i - 1][2] + popcount(cur ^ 7))
ans = min(dp[-1])
print(ans)


def f(l, a):
	(i, count) = (0, 0)
	for x in l:
		count += x not in a[i]
		i = (i + 1) % 2
	return count

def g(l, mx):
	return min([f(l, mx[i]) for i in range(len(mx))])

def two():
	l = [x[0] + x[1] for x in zip(input(), input())]
	mx = ([['00', '11'], ['10', '01']], [['10', '01'], ['00', '11']])
	return g(l, mx)

def three():
	l = [x[0] + x[1] + x[2] for x in zip(input(), input(), input())]
	mx = ([['100', '011'], ['110', '001']], [['110', '001'], ['100', '011']], [['111', '000'], ['010', '101']], [['010', '101'], ['000', '111']])
	return g(l, mx)
nm = input()
(n, m) = [int(x) for x in nm.split()]
if n == 1:
	print(0)
	exit()
if n > 3:
	print(-1)
	exit()
if n == 2:
	print(two())
	exit()
if n == 3:
	print(three())
	exit()


import sys

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

def input_split():
	return [int(i) for i in input().split()]
(n, m) = input_split()
grid = []
for _ in range(n):
	grid.append([int(i) for i in input()])
if n >= 4 and m >= 4:
	ans = -1
elif n < 2 or m < 2:
	ans = 0
elif n == 2 or m == 2:
	if n == 2:
		arr = []
		for i in range(m):
			arr.append((grid[0][i] + grid[1][i]) % 2)
	elif m == 2:
		arr = []
		for i in range(n):
			arr.append((grid[i][0] + grid[i][1]) % 2)
	cost1 = 0
	cost2 = 0
	current = 0
	for i in range(len(arr)):
		cost1 += abs(current - arr[i])
		cost2 += abs(1 - current - arr[i])
		current = 1 - current
	ans = min(cost1, cost2)
elif n == 3 or m == 3:
	if n == 3:
		arr1 = []
		arr2 = []
		for i in range(m):
			arr1.append((grid[0][i] + grid[1][i]) % 2)
			arr2.append((grid[1][i] + grid[2][i]) % 2)
	else:
		arr1 = []
		arr2 = []
		for i in range(n):
			arr1.append((grid[i][0] + grid[i][1]) % 2)
			arr2.append((grid[i][1] + grid[i][2]) % 2)
	cost1 = 0
	cost2 = 0
	cost3 = 0
	cost4 = 0
	current = 0
	for i in range(len(arr1)):
		cost1 += max(abs(current - arr1[i]), abs(current - arr2[i]))
		cost3 += max(abs(current - arr1[i]), abs(1 - current - arr2[i]))
		cost2 += max(abs(1 - current - arr1[i]), abs(1 - current - arr2[i]))
		cost4 += max(abs(1 - current - arr1[i]), abs(current - arr2[i]))
		current = 1 - current
	ans = min(cost1, cost2, cost3, cost4)
print(ans)


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
b = []
D = dict()
for _ in range(n):
	s = input().rstrip()
	b.append(s)
if n > m:
	c = [['0'] * n for i in range(m)]
	for i in range(m):
		for j in range(n):
			c[i][j] = b[j][i]
	(m, n) = (n, m)
	b = c
if n >= 4:
	print(-1)
elif n == 1:
	print(0)
elif n == 2:
	masks = ['00', '01', '10', '11']
	for mask in masks:
		D[mask] = 0
		c = 0
		for bit in mask:
			D[mask] += int(bit) ^ int(b[c][0])
			c += 1
	check = dict()
	DIF = dict()
	for mask in masks:
		check[mask] = []
		for prev_mask in masks:
			(cc, hh) = (0, 0)
			for bit in mask:
				hh += int(bit) ^ int(prev_mask[cc])
				cc += 1
			DIF[mask, prev_mask] = hh
			a = mask[:2] + prev_mask[:2]
			if a.count('1') % 2 == 1:
				check[mask].append(prev_mask)
	for i in range(1, m):
		G = dict()
		temp = b[0][i] + b[1][i]
		for mask in masks:
			G[mask] = float('inf')
			h = DIF[mask, temp]
			if h < 2:
				for prev_mask in check[mask]:
					G[mask] = min(G[mask], D[prev_mask] + h)
		D = G
	ans = float('inf')
	for key in D:
		ans = min(D[key], ans)
	print(ans)
elif n == 3:
	masks = ['000', '001', '010', '011', '100', '101', '110', '111']
	for mask in masks:
		D[mask] = 0
		c = 0
		for bit in mask:
			D[mask] += int(bit) ^ int(b[c][0])
			c += 1
	check = dict()
	DIF = dict()
	for mask in masks:
		check[mask] = []
		for prev_mask in masks:
			(cc, hh) = (0, 0)
			for bit in mask:
				hh += int(bit) ^ int(prev_mask[cc])
				cc += 1
			DIF[mask, prev_mask] = hh
			a = mask[:2] + prev_mask[:2]
			se = mask[1:] + prev_mask[1:]
			if a.count('1') % 2 == 1 and se.count('1') % 2 == 1:
				check[mask].append(prev_mask)
	for i in range(1, m):
		G = dict()
		temp = b[0][i] + b[1][i] + b[2][i]
		for mask in masks:
			G[mask] = float('inf')
			h = DIF[mask, temp]
			if h < 2:
				for prev_mask in check[mask]:
					G[mask] = min(G[mask], D[prev_mask] + h)
		D = G
	ans = float('inf')
	for key in D:
		ans = min(D[key], ans)
	print(ans)


from sys import stdin, stdout, exit

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

def match_same(col):
	if len(set(col)) == 1:
		return 0
	return 1

def match_exact(p, q):
	ret = 0
	for (a, b) in zip(p, q):
		if a != b:
			ret += 1
	return ret

def match_diff(col):
	if len(set(col)) == 1:
		return 1
	if len(col) == 2:
		return 0
	return min(match_exact(col, (0, 1, 0)), match_exact(col, (1, 0, 1)))

def match_sd(col):
	return min(match_exact(col, (1, 1, 0)), match_exact(col, (0, 0, 1)))

def match_ds(col):
	return min(match_exact(col, (0, 1, 1)), match_exact(col, (1, 0, 0)))

def match(col, is_same):
	if is_same:
		return match_same(col)
	else:
		return match_diff(col)

def match_3(col, at_sd):
	if at_sd:
		return match_sd(col)
	else:
		return match_ds(col)

def ans_s(A):
	is_same = True
	ret = 0
	for col in A:
		ret += match(col, is_same)
		is_same = not is_same
	return ret

def ans_d(A):
	is_same = False
	ret = 0
	for col in A:
		ret += match(col, is_same)
		is_same = not is_same
	return ret

def ans_sd(A):
	if len(A[0]) != 3:
		return float('inf')
	at_sd = True
	ret = 0
	for col in A:
		ret += match_3(col, at_sd)
		at_sd = not at_sd
	return ret

def ans_ds(A):
	if len(A[0]) != 3:
		return float('inf')
	at_sd = False
	ret = 0
	for col in A:
		ret += match_3(col, at_sd)
		at_sd = not at_sd
	return ret

def ans(A):
	return min(ans_s(A), ans_d(A), ans_sd(A), ans_ds(A))
(n, m) = input().split()
n = int(n)
m = int(m)
A = []
for _ in range(n):
	A += [input()]
if n >= 4:
	A = [tuple(map(int, row)) for row in A]
	print(-1)
	exit(0)
if n == 1:
	print(0)
	exit(0)
A = zip(*A)
A = [list(map(int, row)) for row in A]
print(ans(A))


import os
import heapq
import sys, threading
import math
import bisect
import operator
from collections import defaultdict
sys.setrecursionlimit(10 ** 5)
from io import BytesIO, IOBase

def gcd(a, b):
	if b == 0:
		return a
	else:
		return gcd(b, a % b)

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

def inar():
	return [int(k) for k in input().split()]

def lcm(num1, num2):
	return num1 * num2 // gcd(num1, num2)

def main():
	(n, m) = inar()
	matrix = []
	for i in range(n):
		take = input()
		matrix.append(take)
	if min(n, m) > 3:
		print(-1)
	elif min(n, m) == 1:
		print(0)
	else:
		if n > m:
			(n, m) = (m, n)
			matrix = [''.join([matrix[j][i] for j in range(m)]) for i in range(n)]
		if n == 2:
			odd = 0
			even = 0
			for i in range(m):
				check = 0
				if i % 2 == 0:
					if matrix[0][i] == '1':
						check += 1
					if matrix[1][i] == '1':
						check += 1
					if check % 2 != 0:
						even += 1
				else:
					if matrix[0][i] == '1':
						check += 1
					if matrix[1][i] == '1':
						check += 1
					if check % 2 == 0:
						even += 1
			for i in range(m):
				check = 0
				if i % 2 == 0:
					if matrix[0][i] == '1':
						check += 1
					if matrix[1][i] == '1':
						check += 1
					if check % 2 == 0:
						odd += 1
				else:
					if matrix[0][i] == '1':
						check += 1
					if matrix[1][i] == '1':
						check += 1
					if check % 2 != 0:
						odd += 1
			print(min(even, odd))
		else:
			ans1 = 0
			for i in range(m):
				changes1 = 0
				changes2 = 0
				if matrix[0][i] == '1':
					changes1 += 1
				if matrix[1][i] == '1':
					changes1 += 1
					changes2 += 1
				if matrix[2][i] == '1':
					changes2 += 1
				if i % 2 == 0:
					if changes1 % 2 == 0 and changes2 % 2 != 0:
						continue
					else:
						ans1 += 1
				elif changes1 % 2 != 0 and changes2 % 2 == 0:
					continue
				else:
					ans1 += 1
			ans2 = 0
			for i in range(m):
				changes1 = 0
				changes2 = 0
				if matrix[0][i] == '1':
					changes1 += 1
				if matrix[1][i] == '1':
					changes1 += 1
					changes2 += 1
				if matrix[2][i] == '1':
					changes2 += 1
				if i % 2 == 0:
					if changes1 % 2 != 0 and changes2 % 2 == 0:
						continue
					else:
						ans2 += 1
				elif changes1 % 2 == 0 and changes2 % 2 != 0:
					continue
				else:
					ans2 += 1
			ans3 = 0
			for i in range(m):
				changes1 = 0
				changes2 = 0
				if matrix[0][i] == '1':
					changes1 += 1
				if matrix[1][i] == '1':
					changes1 += 1
					changes2 += 1
				if matrix[2][i] == '1':
					changes2 += 1
				if i % 2 == 0:
					if changes1 % 2 == 0 and changes2 % 2 == 0:
						continue
					else:
						ans3 += 1
				elif changes1 % 2 != 0 and changes2 % 2 != 0:
					continue
				else:
					ans3 += 1
			ans4 = 0
			for i in range(m):
				changes1 = 0
				changes2 = 0
				if matrix[0][i] == '1':
					changes1 += 1
				if matrix[1][i] == '1':
					changes1 += 1
					changes2 += 1
				if matrix[2][i] == '1':
					changes2 += 1
				if i % 2 == 0:
					if changes1 % 2 != 0 and changes2 % 2 != 0:
						continue
					else:
						ans4 += 1
				elif changes1 % 2 == 0 and changes2 % 2 == 0:
					continue
				else:
					ans4 += 1
			print(min(ans1, ans2, ans3, ans4))
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 io
import os
from collections import Counter, defaultdict, deque

def solve(R, C, grid):
	if R == 1 or C == 1:
		return 0
	if R >= 4 and C >= 4:
		return -1
	colMasks = []
	if R < C:
		transposed = [[0 for r in range(R)] for c in range(C)]
		for r in range(R):
			for c in range(C):
				transposed[c][r] = grid[r][c]
		(R, C) = (C, R)
		grid = transposed
	assert C <= R
	assert 2 <= C < 4
	colMasks = []
	for r in range(R):
		mask = 0
		for c in range(C):
			mask |= grid[r][c] << c
		colMasks.append(mask)
	numMasks = 1 << C
	graph = [[] for i in range(numMasks)]
	for prevMask in range(numMasks):
		for mask in range(numMasks):
			good = True
			vert = mask ^ prevMask
			for c in range(C - 1):
				a = vert >> c & 1
				b = vert >> c + 1 & 1
				if a ^ b == 0:
					good = False
					break
			if good:
				graph[prevMask].append(mask)
	popcount = []
	for mask in range(numMasks):
		popcount.append(bin(mask).count('1'))
	inf = 10000000
	dp = [[inf for i in range(R)] for j in range(numMasks)]
	for mask in range(numMasks):
		dp[mask][0] = popcount[mask ^ colMasks[0]]
	for r in range(1, R):
		for mask in range(numMasks):
			best = inf
			cost = popcount[mask ^ colMasks[r]]
			for prevMask in graph[mask]:
				best = min(best, cost + dp[prevMask][r - 1])
			dp[mask][r] = best
	best = min((dp[mask][R - 1] for mask in range(1 << C)))
	if best >= inf:
		return -1
	return best
if False:

	def isGood(grid):
		for r in range(R - 1):
			for c in range(C - 1):
				count = 0
				for dr in range(2):
					for dc in range(2):
						count += grid[r + dr][c + dc]
				if count % 2 != 1:
					return False
		return True
	(R, C) = (3, 4)
	for mask in range(1 << R * C):
		grid = [[0 for c in range(C)] for r in range(R)]
		for r in range(R):
			for c in range(C):
				grid[r][c] = int(bool(mask & 1 << r * C + c))
		if isGood(grid):
			print(mask)
			for row in grid:
				print(row)
	exit()
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
(N, M) = [int(x) for x in input().split()]
grid = [[int(x) for x in input().decode().rstrip()] for i in range(N)]
ans = solve(N, M, grid)
print(ans)


def checkPairable(b1, b2, n):
	ok = True
	for start in range(n - 1):
		cnt = 0
		if b1 & 1 << start > 0:
			cnt += 1
		if b1 & 1 << start + 1 > 0:
			cnt += 1
		if b2 & 1 << start > 0:
			cnt += 1
		if b2 & 1 << start + 1 > 0:
			cnt += 1
		if cnt % 2 == 0:
			ok = False
	return ok

def nMovesB1toB2(b1, b2, n):
	res = 0
	for i in range(n):
		if (b1 & 1 << i > 0) != (b2 & 1 << i > 0):
			res += 1
	return res

def main():
	(n, m) = readIntArr()
	mat = []
	for _ in range(n):
		mat.append(input())
	if n >= 4:
		print(-1)
		return
	if n == 1:
		print(0)
		return
	cols = []
	for j in range(m):
		b = 0
		for i in range(n):
			if mat[i][j] == '1':
				b = b | 1 << i
		cols.append(b)
	pairableCols = [[] for _ in range(2 ** n)]
	for b1 in range(2 ** n):
		for b2 in range(2 ** n):
			if checkPairable(b1, b2, n):
				pairableCols[b1].append(b2)
	dp = [[float('inf') for _ in range(2 ** n)] for __ in range(m)]
	for b in range(2 ** n):
		dp[0][b] = min(dp[0][b], nMovesB1toB2(cols[0], b, n))
	for col in range(1, m):
		for b in range(2 ** n):
			moveCnt = nMovesB1toB2(cols[col], b, n)
			for matchedPrev in pairableCols[b]:
				dp[col][b] = min(dp[col][b], moveCnt + dp[col - 1][matchedPrev])
	ans = float('inf')
	for b in range(2 ** n):
		ans = min(ans, dp[m - 1][b])
	print(ans)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

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

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

def readIntArr():
	return [int(x) for x in input().split()]
main()


def gen_changes_table(threes):
	table = []
	for (c, three) in enumerate(threes):
		line = []
		for (c2, three2) in enumerate(threes):
			total = 0
			for i in range(3):
				if three[i] != three2[i]:
					total += 1
			line.append(total)
		table.append(line)
	return table

def main():
	(n, m) = map(int, input().split())
	if n == 1 or n > 3:
		for _ in range(n):
			__ = input()
		if n == 1:
			print(0)
		else:
			print(-1)
		return
	elif n == 2:
		(first, second) = (input(), input())
		one_first = one_second = 0
		for i in range(m):
			line = first[i] + second[i]
			num = line.count('0')
			if i % 2 == num % 2:
				one_first += 1
			else:
				one_second += 1
		print(min(one_first, one_second))
	else:
		threes_l = ['111', '011', '101', '001', '110', '010', '100', '000']
		threes = {threes_l[x]: x for x in range(8)}
		table = gen_changes_table(threes_l)
		routes = [0, 0, 0, 0]
		(first, second, third) = (input(), input(), input())
		for i in range(m):
			line = first[i] + second[i] + third[i]
			raw_three_num = threes[line]
			if i % 2 == 0:
				for j in range(4):
					routes[j] += min(table[raw_three_num][j], table[raw_three_num][7 - j])
			else:
				for j in range(4):
					new_j = (j + 2) % 4
					routes[j] += min(table[raw_three_num][new_j], table[raw_three_num][7 - new_j])
		print(min(routes))
main()


(n, m) = map(int, input().split())
if min(n, m) > 3:
	print(-1)
	exit()
if min(n, m) == 1:
	print(0)
	exit()
if n > m:
	inp = []
	for i in range(n):
		inp.append(list(map(int, input().split())))
	u = []
	(n, m) = (m, n)
	for i in range(n):
		u.append([0] * m)
	for i in range(n):
		for j in range(m):
			u[i][j] = inp[j][i]
else:
	u = []
	for i in range(n):
		u.append(list(map(int, list(input()))))
if n == 2:
	d = [0] * m
	for j in range(m):
		if u[0][j] + u[1][j] == 1:
			d[j] = 1
	cnt1 = 0
	cnt2 = 0
	for j in range(m):
		if d[j] % 2 == j % 2:
			cnt1 += 1
		else:
			cnt2 += 1
	print(min(cnt1, cnt2))
else:
	d1 = [0] * m
	d2 = [0] * m
	for j in range(m):
		if u[0][j] + u[1][j] == 1:
			d1[j] = 1
		if u[1][j] + u[2][j] == 1:
			d2[j] = 1
	cnt1 = cnt2 = cnt3 = cnt4 = 0
	for j in range(m):
		r1 = d1[j] % 2 == j % 2
		r2 = d2[j] % 2 == j % 2
		if r1 and r2:
			cnt2 += 1
			cnt3 += 1
			cnt4 += 1
		elif r1:
			cnt1 += 1
			cnt3 += 1
			cnt4 += 1
		elif r2:
			cnt1 += 1
			cnt2 += 1
			cnt4 += 1
		else:
			cnt1 += 1
			cnt2 += 1
			cnt3 += 1
	print(min(cnt1, cnt2, cnt3, cnt4))


from sys import stdin
input = stdin.readline
(n, m) = map(int, input().split())
a = []
for x in range(n):
	a.append(input().rstrip())
if n == 1:
	print(0)
elif n >= 4:
	print(-1)
elif n == 2:
	(cnt1, cnt2) = (0, 0)
	for x in range(m):
		if x % 2 == 0:
			cnt1 += a[0][x] == a[1][x]
			cnt2 += a[0][x] != a[1][x]
		else:
			cnt1 += a[0][x] != a[1][x]
			cnt2 += a[0][x] == a[1][x]
	print(min(cnt1, cnt2))
elif n == 3:
	(cnt1, cnt2, cnt3, cnt4) = (0, 0, 0, 0)
	for x in range(m):
		if x % 2 == 0:
			if a[0][x] == a[1][x] == a[2][x]:
				cnt1 += 0
			else:
				cnt1 += 1
			if a[0][x] == a[2][x] and a[0][x] != a[1][x]:
				cnt2 += 0
			else:
				cnt2 += 1
		else:
			if a[0][x] == a[2][x] and a[0][x] != a[1][x]:
				cnt1 += 0
			else:
				cnt1 += 1
			if a[0][x] == a[1][x] == a[2][x]:
				cnt2 += 0
			else:
				cnt2 += 1
		if x % 2 == 0:
			if a[0][x] == a[1][x] and a[0][x] != a[2][x]:
				cnt3 += 0
			else:
				cnt3 += 1
			if a[1][x] == a[2][x] and a[0][x] != a[1][x]:
				cnt4 += 0
			else:
				cnt4 += 1
		else:
			if a[1][x] == a[2][x] and a[0][x] != a[1][x]:
				cnt3 += 0
			else:
				cnt3 += 1
			if a[0][x] == a[1][x] and a[0][x] != a[2][x]:
				cnt4 += 0
			else:
				cnt4 += 1
	print(min(cnt1, cnt2, cnt3, cnt4))


import sys
input = sys.stdin.readline
(n, m) = list(map(int, input().split()))
a = []

def f(x, y):
	res = 0
	if x[0] != y[0]:
		res += 1
	if x[1] != y[1]:
		res += 1
	if x[2] != y[2]:
		res += 1
	return res
if n >= 4 and m >= 4:
	for i in range(n):
		a.append(list(input()))
	print(-1)
elif n == 1 or m == 1:
	for i in range(n):
		a.append(list(input()))
	print(0)
elif n == 2 or m == 2:
	c = []
	if m == 2:
		for i in range(n):
			s = list(input())
			c.append(s.count('1') % 2)
	elif n == 2:
		for i in range(n):
			a.append(list(input()))
		for i in range(m):
			tmp = 0
			if a[0][i] == '1':
				tmp += 1
			if a[1][i] == '1':
				tmp += 1
			c.append(tmp % 2)
	res1 = 0
	res2 = 0
	for i in range(len(c)):
		if i % 2 == c[i]:
			res1 += 1
		else:
			res2 += 1
	print(min(res1, res2))
else:
	a = []
	if n == 3:
		b = list(input())
		c = list(input())
		d = list(input())
		for i in range(m):
			a.append(b[i] + c[i] + d[i])
	elif m == 3:
		s = input()
		a.append(s)
	r = max(n, m)
	res1 = 0
	res2 = 0
	res3 = 0
	res4 = 0
	for i in range(r):
		if i % 2 == 0:
			res1 += min(f(a[i], '111'), f(a[i], '000'))
			res2 += min(f(a[i], '010'), f(a[i], '101'))
			res3 += min(f(a[i], '110'), f(a[i], '001'))
			res4 += min(f(a[i], '011'), f(a[i], '100'))
		else:
			res2 += min(f(a[i], '111'), f(a[i], '000'))
			res1 += min(f(a[i], '010'), f(a[i], '101'))
			res4 += min(f(a[i], '110'), f(a[i], '001'))
			res3 += min(f(a[i], '011'), f(a[i], '100'))
	print(min(res1, res2, res3, res4))


import sys
(n, m) = map(int, input().split())
grid = []
for i in range(n):
	grid.append(input())
if min(n, m) >= 4:
	print(-1)
	sys.exit()
if min(n, m) < 2:
	print(0)
	sys.exit()
nflag = 0
flag2 = 0
if min(n, m) == n:
	nflag = 1
if min(n, m) == 2:
	flag2 = 1
if flag2 == 1:
	if nflag == 1:
		d = []
		for i in range(m - 1):
			k = 0
			if grid[0][i] == '1':
				k = 1 - k
			if grid[0][i + 1] == '1':
				k = 1 - k
			if grid[1][i] == '1':
				k = 1 - k
			if grid[1][i + 1] == '1':
				k = 1 - k
			d.append(k)
		tr = [0] * (m + 1)
		flag = 0
		for i in range(m - 1):
			if d[i] == 0:
				flag = 1 - flag
			tr[i + 1] = flag
		ans = sum(tr)
		tr = [0] * (m + 1)
		flag = 1
		tr[0] = 1
		for i in range(m - 1):
			if d[i] == 0:
				flag = 1 - flag
			tr[i + 1] = flag
		ans = min(ans, sum(tr))
		print(ans)
	else:
		d = []
		for i in range(n - 1):
			k = 0
			if grid[i][0] == '1':
				k = 1 - k
			if grid[i + 1][0] == '1':
				k = 1 - k
			if grid[i][1] == '1':
				k = 1 - k
			if grid[i + 1][1] == '1':
				k = 1 - k
			d.append(k)
		tr = [0] * (n + 1)
		flag = 0
		for i in range(n - 1):
			if d[i] == 0:
				flag = 1 - flag
			tr[i + 1] = flag
		ans = sum(tr)
		tr = [0] * (n + 1)
		flag = 1
		tr[0] = 1
		for i in range(n - 1):
			if d[i] == 0:
				flag = 1 - flag
			tr[i + 1] = flag
		ans = min(ans, sum(tr))
		print(ans)
elif nflag == 1:
	d = []
	for i in range(m - 1):
		k = 0
		if grid[0][i] == '1':
			k = 1 - k
		if grid[0][i + 1] == '1':
			k = 1 - k
		if grid[1][i] == '1':
			k = 1 - k
		if grid[1][i + 1] == '1':
			k = 1 - k
		d.append(k)
	d2 = []
	for i in range(m - 1):
		k = 0
		if grid[1][i] == '1':
			k = 1 - k
		if grid[1][i + 1] == '1':
			k = 1 - k
		if grid[2][i] == '1':
			k = 1 - k
		if grid[2][i + 1] == '1':
			k = 1 - k
		d2.append(k)
	tr = []
	for i in range(m + 1):
		tr.append([0, 0])
	flag = 0
	for i in range(m - 1):
		if d[i] == 0:
			flag = 1 - flag
		tr[i + 1][0] = flag
	flag = 0
	for i in range(m - 1):
		if d2[i] == 0:
			flag = 1 - flag
		tr[i + 1][1] = flag
	ans = 0
	for i in range(m + 1):
		if tr[i][0] or tr[i][1]:
			ans += 1
	tr = []
	for i in range(m + 1):
		tr.append([0, 0])
	flag = 0
	for i in range(m - 1):
		if d[i] == 0:
			flag = 1 - flag
		tr[i + 1][0] = flag
	flag = 1
	tr[0][1] = 1
	for i in range(m - 1):
		if d2[i] == 0:
			flag = 1 - flag
		tr[i + 1][1] = flag
	tmp = 0
	for i in range(m + 1):
		if tr[i][0] or tr[i][1]:
			tmp += 1
	ans = min(tmp, ans)
	tr = []
	for i in range(m + 1):
		tr.append([0, 0])
	tr[0][0] = 1
	flag = 1
	for i in range(m - 1):
		if d[i] == 0:
			flag = 1 - flag
		tr[i + 1][0] = flag
	flag = 0
	for i in range(m - 1):
		if d2[i] == 0:
			flag = 1 - flag
		tr[i + 1][1] = flag
	tmp = 0
	for i in range(m + 1):
		if tr[i][0] or tr[i][1]:
			tmp += 1
	ans = min(tmp, ans)
	tr = []
	for i in range(m + 1):
		tr.append([0, 0])
	flag = 1
	tr[0][0] = 1
	for i in range(m - 1):
		if d[i] == 0:
			flag = 1 - flag
		tr[i + 1][0] = flag
	flag = 1
	tr[0][1] = 1
	for i in range(m - 1):
		if d2[i] == 0:
			flag = 1 - flag
		tr[i + 1][1] = flag
	tmp = 0
	for i in range(m + 1):
		if tr[i][0] or tr[i][1]:
			tmp += 1
	ans = min(tmp, ans)
	print(ans)
else:
	d = []
	for i in range(n - 1):
		k = 0
		if grid[i][0] == '1':
			k = 1 - k
		if grid[i + 1][0] == '1':
			k = 1 - k
		if grid[i][1] == '1':
			k = 1 - k
		if grid[i + 1][1] == '1':
			k = 1 - k
		d.append(k)
	d2 = []
	for i in range(n - 1):
		k = 0
		if grid[i][1] == '1':
			k = 1 - k
		if grid[i + 1][1] == '1':
			k = 1 - k
		if grid[i][2] == '1':
			k = 1 - k
		if grid[i + 1][2] == '1':
			k = 1 - k
		d2.append(k)
	tr = []
	for i in range(n + 1):
		tr.append([0, 0])
	flag = 0
	for i in range(n - 1):
		if d[i] == 0:
			flag = 1 - flag
		tr[i + 1][0] = flag
	flag = 0
	for i in range(n - 1):
		if d2[i] == 0:
			flag = 1 - flag
		tr[i + 1][1] = flag
	ans = 0
	for i in range(n + 1):
		if tr[i][0] or tr[i][1]:
			ans += 1
	tr = []
	for i in range(n + 1):
		tr.append([0, 0])
	flag = 0
	for i in range(n - 1):
		if d[i] == 0:
			flag = 1 - flag
		tr[i + 1][0] = flag
	flag = 1
	tr[0][1] = 1
	for i in range(n - 1):
		if d2[i] == 0:
			flag = 1 - flag
		tr[i + 1][1] = flag
	tmp = 0
	for i in range(n + 1):
		if tr[i][0] or tr[i][1]:
			tmp += 1
	ans = min(tmp, ans)
	tr = []
	for i in range(n + 1):
		tr.append([0, 0])
	tr[0][0] = 1
	flag = 1
	for i in range(n - 1):
		if d[i] == 0:
			flag = 1 - flag
		tr[i + 1][0] = flag
	flag = 0
	for i in range(n - 1):
		if d2[i] == 0:
			flag = 1 - flag
		tr[i + 1][1] = flag
	tmp = 0
	for i in range(n + 1):
		if tr[i][0] or tr[i][1]:
			tmp += 1
	ans = min(tmp, ans)
	tr = []
	for i in range(n + 1):
		tr.append([0, 0])
	flag = 1
	tr[0][0] = 1
	for i in range(n - 1):
		if d[i] == 0:
			flag = 1 - flag
		tr[i + 1][0] = flag
	flag = 1
	tr[0][1] = 1
	for i in range(n - 1):
		if d2[i] == 0:
			flag = 1 - flag
		tr[i + 1][1] = flag
	tmp = 0
	for i in range(n + 1):
		if tr[i][0] or tr[i][1]:
			tmp += 1
	ans = min(tmp, ans)
	print(ans)


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
mat = []
for i in range(n):
	mat.append([int(i) for i in input() if i != '\n'])
if n >= 4:
	print(-1)
elif n == 1 or m == 1:
	print(0)
elif n == 2:
	(odd, even) = (False, False)
	(ans1, ans2) = (0, 1)
	if mat[0][0] + mat[1][0] & 1:
		odd = True
	else:
		even = True
	for i in range(1, m):
		if odd:
			if mat[0][i] + mat[1][i] & 1:
				ans1 += 1
				odd = False
				even = True
			else:
				odd = False
				even = True
		elif mat[0][i] + mat[1][i] & 1:
			odd = True
			even = False
		else:
			ans1 += 1
			odd = True
	if mat[0][0] + mat[1][0] & 1:
		even = True
	else:
		odd = True
	for i in range(1, m):
		if odd:
			if mat[0][i] + mat[1][i] & 1:
				ans2 += 1
				odd = False
				even = True
			else:
				odd = False
				even = True
		elif mat[0][i] + mat[1][i] & 1:
			odd = True
			even = False
		else:
			ans2 += 1
			odd = True
			even = False
	print(min(ans1, ans2))
elif n == 3:
	A = mat
	DP0 = [1 << 30] * m
	DP1 = [1 << 30] * m
	DP2 = [1 << 30] * m
	DP3 = [1 << 30] * m
	if (A[0][0] + A[1][0]) % 2 == 0 and (A[1][0] + A[2][0]) % 2 == 0:
		DP0[0] = 0
		DP1[0] = 1
		DP2[0] = 1
		DP3[0] = 1
	elif (A[0][0] + A[1][0]) % 2 == 0 and (A[1][0] + A[2][0]) % 2 == 1:
		DP0[0] = 1
		DP1[0] = 0
		DP2[0] = 1
		DP3[0] = 1
	elif (A[0][0] + A[1][0]) % 2 == 1 and (A[1][0] + A[2][0]) % 2 == 0:
		DP0[0] = 1
		DP1[0] = 1
		DP2[0] = 0
		DP3[0] = 1
	elif (A[0][0] + A[1][0]) % 2 == 1 and (A[1][0] + A[2][0]) % 2 == 1:
		DP0[0] = 1
		DP1[0] = 1
		DP2[0] = 1
		DP3[0] = 0
	for i in range(1, m):
		if (A[0][i] + A[1][i]) % 2 == 0 and (A[1][i] + A[2][i]) % 2 == 0:
			DP0[i] = DP3[i - 1]
			DP1[i] = DP2[i - 1] + 1
			DP2[i] = DP1[i - 1] + 1
			DP3[i] = DP0[i - 1] + 1
		elif (A[0][i] + A[1][i]) % 2 == 0 and (A[1][i] + A[2][i]) % 2 == 1:
			DP0[i] = DP3[i - 1] + 1
			DP1[i] = DP2[i - 1]
			DP2[i] = DP1[i - 1] + 1
			DP3[i] = DP0[i - 1] + 1
		elif (A[0][i] + A[1][i]) % 2 == 1 and (A[1][i] + A[2][i]) % 2 == 0:
			DP0[i] = DP3[i - 1] + 1
			DP1[i] = DP2[i - 1] + 1
			DP2[i] = DP1[i - 1]
			DP3[i] = DP0[i - 1] + 1
		elif (A[0][i] + A[1][i]) % 2 == 1 and (A[1][i] + A[2][i]) % 2 == 1:
			DP0[i] = DP3[i - 1] + 1
			DP1[i] = DP2[i - 1] + 1
			DP2[i] = DP1[i - 1] + 1
			DP3[i] = DP0[i - 1]
	print(min(DP0[-1], DP1[-1], DP2[-1], DP3[-1]))


from itertools import chain, product

def find_cells_to_fix_n(matrix):
	if len(matrix) < 2 or len(matrix[0]) < 2:
		return 0
	if not len(matrix) <= len(matrix[0]):
		matrix = tuple(zip(*matrix))
	(len_y, len_x) = (len(matrix), len(matrix[0]))
	if len_y >= 4:
		result = None
	elif len_y == 3:
		result = _solve_for_3(matrix)
	elif len_y == 2:
		result = _solve_for_2(matrix)
	else:
		raise AssertionError("can't get here")
	return result

def _compress_2xn(matrix):
	assert len(matrix) == 2
	parity_line = tuple(map(int.__add__, *matrix))
	parity_line = map(int.__add__, parity_line, parity_line[1:])
	parity_line = map(2 .__rmod__, parity_line)
	parity_line = tuple(parity_line)
	return parity_line

def _compress_3xn(matrix):
	assert len(matrix) == 3
	first_row = _compress_2xn(matrix[0:2])
	second_row = _compress_2xn(matrix[1:3])
	result = (first_row, second_row)
	return result

def _get_zeros_pairs(zeros_positions, line_length, is_first_towards_left):
	if not zeros_positions:
		return []
	if is_first_towards_left:
		zeros_pairs = [(-1, zeros_positions[0])]
	else:
		zeros_pairs = []
	i_start_zero = 1 if is_first_towards_left else 0
	for i_first_zero in range(i_start_zero, len(zeros_positions), 2):
		i_second_zero = i_first_zero + 1
		first_zero_pos = zeros_positions[i_first_zero]
		if i_second_zero < len(zeros_positions):
			second_zero_pos = zeros_positions[i_second_zero]
		else:
			second_zero_pos = line_length
		zeros_pairs.append((first_zero_pos, second_zero_pos))
	return zeros_pairs

def _find_zeros_pairs_costs(zeros_pairs):
	return sum((second_pos - first_pos for (first_pos, second_pos) in zeros_pairs))

def _solve_for_2(matrix):
	parity_line = _compress_2xn(matrix)
	zeros_positions = tuple((i for (i, value) in enumerate(parity_line) if value == 0))
	line_length = len(parity_line)
	min_cost = min((_how_much_costs_tactic_for_2xn(zeros_positions, line_length, is_first_towards_left) for is_first_towards_left in (True, False)))
	return min_cost

def _how_much_costs_tactic_for_2xn(zeros_positions, line_length, is_first_towards_left):
	zeros_pairs = _get_zeros_pairs(zeros_positions, line_length, is_first_towards_left)
	return _find_zeros_pairs_costs(zeros_pairs)

def _solve_for_3(matrix):
	parity_lines = _compress_3xn(matrix)
	zeros_positions = tuple((tuple((i for (i, value) in enumerate(parity_line) if value == 0)) for parity_line in parity_lines))
	line_length = len(parity_lines[0])
	min_cost = min((_how_much_costs_tactic_for_3xn(zeros_positions, line_length, is_first_towards_left) for is_first_towards_left in product((True, False), repeat=2)))
	return min_cost

def _how_much_costs_tactic_for_3xn(zeros_positions, line_length, is_first_towards_left):
	zeros_pairs = tuple((_get_zeros_pairs(_zeros_positions, line_length, _is_first_towards_left) for (_zeros_positions, _is_first_towards_left) in zip(zeros_positions, is_first_towards_left)))
	(first_row_pairs, second_row_pairs) = zeros_pairs
	walked = [0] * (line_length + 1)
	for (pair_first, pair_last) in chain(first_row_pairs, second_row_pairs):
		for i in range(pair_first, pair_last):
			walked[i + 1] = 1
	return sum(walked)

def main():
	(n, m) = map(int, input().split())
	matrix = tuple((tuple(map(int, input())) for i in range(n)))
	cells_to_fix_n = find_cells_to_fix_n(matrix)
	if cells_to_fix_n is None:
		cells_to_fix_n = -1
	print(cells_to_fix_n)
main()


import sys
input = sys.stdin.readline
(n, m) = list(map(int, input().split()))
masks = ['000', '001', '010', '011', '100', '101', '110', '111']
D = {}
x = []
for _ in range(n):
	l = input().rstrip()
	x.append(l)
if n < 2:
	print(0)
if n == 2:
	masks = ['00', '01', '10', '11']
	for mask in masks:
		D[mask] = 0
		c = 0
		for bit in mask:
			D[mask] += int(bit) ^ int(x[c][0])
			c += 1
	check = {}
	DIF = {}
	for mask in masks:
		check[mask] = []
		for prev_mask in masks:
			(cc, hh) = (0, 0)
			for bit in mask:
				hh += int(bit) ^ int(prev_mask[cc])
				cc += 1
			DIF[mask, prev_mask] = hh
			a = mask[:2] + prev_mask[:2]
			if a.count('1') % 2 == 1:
				check[mask].append(prev_mask)
	for i in range(1, m):
		G = {}
		temp = x[0][i] + x[1][i]
		for mask in masks:
			G[mask] = 99999999
			h = DIF[mask, temp]
			if h < 2:
				for prev_mask in check[mask]:
					G[mask] = min(G[mask], D[prev_mask] + h)
		D = G
	ans = 99999999
	for key in D:
		ans = min(D[key], ans)
	print(ans)
if n == 3:
	for mask in masks:
		D[mask] = 0
		c = 0
		for bit in mask:
			D[mask] += int(bit) ^ int(x[c][0])
			c += 1
	check = {}
	DIF = {}
	for mask in masks:
		check[mask] = []
		for prev_mask in masks:
			(cc, hh) = (0, 0)
			for bit in mask:
				hh += int(bit) ^ int(prev_mask[cc])
				cc += 1
			DIF[mask, prev_mask] = hh
			a = mask[:2] + prev_mask[:2]
			b = mask[1:] + prev_mask[1:]
			if a.count('1') % 2 == 1 and b.count('1') % 2 == 1:
				check[mask].append(prev_mask)
	for i in range(1, m):
		G = {}
		temp = x[0][i] + x[1][i] + x[2][i]
		for mask in masks:
			G[mask] = 99999999
			h = DIF[mask, temp]
			if h < 2:
				for prev_mask in check[mask]:
					G[mask] = min(G[mask], D[prev_mask] + h)
		D = G
	ans = 99999999
	for key in D:
		ans = min(D[key], ans)
	print(ans)
if n > 3:
	print(-1)


(n, m) = map(int, input().split())
if min(n, m) == 1:
	print(0)
elif n >= 4:
	print(-1)
elif n == 2:
	lis = []
	c = d = 0
	for i in range(2):
		s = list(input())
		lis.append(s)
	for i in range(m):
		if (int(lis[0][i]) + int(lis[1][i]) + i) % 2:
			c += 1
		else:
			d += 1
	print(min(c, d))
else:
	lis = []
	c = d = 0
	ans = [0, 0, 0, 0]
	for i in range(3):
		s = list(input())
		lis.append(s)
	for i in range(m):
		c = (int(lis[0][i]) + int(lis[1][i])) % 2
		d = (int(lis[1][i]) + int(lis[2][i])) % 2
		if i % 2 == 0:
			if d != 0 or c != 0:
				ans[0] += 1
			if d == 0 or c == 0:
				ans[1] += 1
			if c != 0 or d != 1:
				ans[2] += 1
			if c != 1 or d != 0:
				ans[3] += 1
		else:
			if d != 0 or c != 0:
				ans[1] += 1
			if d == 0 or c == 0:
				ans[0] += 1
			if c != 1 or d != 0:
				ans[2] += 1
			if c != 0 or d != 1:
				ans[3] += 1
	print(min(ans))


def is_valid(prev_mask, curr_mask, N):
	bits = prev_mask ^ curr_mask
	if N == 2:
		return bits != 0 and bits != 3
	else:
		check1 = bits != 0 and bits != 1 and (bits != 4)
		check2 = bits != 7 and bits != 6 and (bits != 3)
		return check1 and check2

def solve():
	(N, M) = map(int, input().split())
	A = [list(map(int, input())) for _ in range(N)]
	if N >= 4 and M >= 4:
		return -1
	if N == 1 or M == 1:
		return 0
	state = [0] * M
	for c in range(M):
		for r in range(N):
			if A[r][c] == 1:
				state[c] |= 1 << N - 1 - r
	popcounts = [bin(x).count('1') for x in range(1 << N)]
	dp = [[N * M] * (1 << N) for _ in range(M)]
	for mask in range(1 << N):
		dp[0][mask] = popcounts[state[0] ^ mask]
	for i in range(1, M):
		for curr_mask in range(1 << N):
			dp[i][curr_mask] = min([dp[i - 1][prev_mask] for prev_mask in range(1 << N) if is_valid(prev_mask, curr_mask, N)]) + popcounts[state[i] ^ curr_mask]
	return min(dp[-1])
print(solve())


from sys import stdin, stdout

def getans(n, m, arr):
	if n == 2 or m == 2:
		lim = 0
		if m == 2:
			lim = n
			mark = [(arr[i][0] + arr[i][1]) % 2 for i in range(lim)]
			sol = [[0 for i in range(lim)] for j in range(2)]
		else:
			lim = m
			mark = [(arr[0][i] + arr[1][i]) % 2 for i in range(lim)]
			sol = [[0 for i in range(lim)] for j in range(2)]
		for i in range(lim):
			if i % 2 == 0:
				if mark[i] == 0:
					sol[1][i] = sol[1][i - 1] + 1
					sol[0][i] = sol[0][i - 1]
				else:
					sol[0][i] = sol[0][i - 1] + 1
					sol[1][i] = sol[1][i - 1]
			elif mark[i] == 0:
				sol[0][i] = sol[0][i - 1] + 1
				sol[1][i] = sol[1][i - 1]
			else:
				sol[1][i] = sol[1][i - 1] + 1
				sol[0][i] = sol[0][i - 1]
		return min(sol[0][-1], sol[1][-1])
	elif n == 3 or m == 3:
		lim = 0
		if m == 3:
			lim = n
			mark = [[(arr[i][0] + arr[i][1]) % 2 for i in range(lim)], [(arr[i][1] + arr[i][2]) % 2 for i in range(lim)]]
			sol = [[0 for i in range(lim)] for j in range(4)]
		else:
			lim = m
			mark = [[(arr[0][i] + arr[1][i]) % 2 for i in range(lim)], [(arr[1][i] + arr[2][i]) % 2 for i in range(lim)]]
			sol = [[0 for i in range(lim)] for j in range(4)]
		for i in range(lim):
			if i % 2 == 0:
				if mark[0][i] % 2 == 0:
					if mark[1][i] % 2 == 0:
						sol[0][i] = sol[0][i - 1]
						sol[1][i] = sol[1][i - 1] + 1
						sol[2][i] = sol[2][i - 1] + 1
						sol[3][i] = sol[3][i - 1] + 1
					else:
						sol[0][i] = sol[0][i - 1] + 1
						sol[1][i] = sol[1][i - 1] + 1
						sol[2][i] = sol[2][i - 1]
						sol[3][i] = sol[3][i - 1] + 1
				elif mark[1][i] % 2 == 0:
					sol[0][i] = sol[0][i - 1] + 1
					sol[1][i] = sol[1][i - 1] + 1
					sol[2][i] = sol[2][i - 1] + 1
					sol[3][i] = sol[3][i - 1]
				else:
					sol[0][i] = sol[0][i - 1] + 1
					sol[1][i] = sol[1][i - 1]
					sol[2][i] = sol[2][i - 1] + 1
					sol[3][i] = sol[3][i - 1] + 1
			elif mark[0][i] % 2 == 0:
				if mark[1][i] % 2 == 0:
					sol[0][i] = sol[0][i - 1] + 1
					sol[1][i] = sol[1][i - 1]
					sol[2][i] = sol[2][i - 1] + 1
					sol[3][i] = sol[3][i - 1] + 1
				else:
					sol[0][i] = sol[0][i - 1] + 1
					sol[1][i] = sol[1][i - 1] + 1
					sol[2][i] = sol[2][i - 1] + 1
					sol[3][i] = sol[3][i - 1]
			elif mark[1][i] % 2 == 0:
				sol[0][i] = sol[0][i - 1] + 1
				sol[1][i] = sol[1][i - 1] + 1
				sol[2][i] = sol[2][i - 1]
				sol[3][i] = sol[3][i - 1] + 1
			else:
				sol[0][i] = sol[0][i - 1]
				sol[1][i] = sol[1][i - 1] + 1
				sol[2][i] = sol[2][i - 1] + 1
				sol[3][i] = sol[3][i - 1] + 1
		return min(sol[0][-1], sol[1][-1], sol[2][-1], sol[3][-1])

def solve(n, m, arr):
	if n >= 4 and m >= 4:
		return -1
	elif n == 1 or m == 1:
		return 0
	else:
		return getans(n, m, arr)
(n, m) = map(int, stdin.readline().strip().split(' '))
arr = []
for i in range(n):
	arr.append(list(map(int, list(stdin.readline().strip()))))
stdout.write(str(solve(n, m, arr)) + '\n')


(n, m) = map(int, input().split())
if n > 3:
	print(-1)
elif n == 1:
	print(0)
else:
	l = []
	for i in range(n):
		temp = list(map(int, list(input())))
		l.append(temp)
	if n == 2:
		A = l[:]
		BU = [(A[0][i] + A[1][i]) % 2 for i in range(m)]
		odd = 0
		even = 0
		for i in range(m):
			if BU[i] % 2 == i % 2:
				odd += 1
			else:
				even += 1
		print(min(even, odd))
	else:
		newLU = []
		newLD = []
		ans = 0
		A = l[:]
		BU = [(A[0][i] + A[1][i]) % 2 for i in range(m)]
		BD = [(A[1][i] + A[2][i]) % 2 for i in range(m)]
		oddodd = 0
		oddeven = 0
		evenodd = 0
		eveneven = 0
		for i in range(m):
			if BU[i] == i % 2 and BD[i] == i % 2:
				oddodd -= 1
			if BU[i] != i % 2 and BD[i] == i % 2:
				evenodd -= 1
			if BU[i] != i % 2 and BD[i] != i % 2:
				eveneven -= 1
			if BU[i] == i % 2 and BD[i] != i % 2:
				oddeven -= 1
			oddeven += 1
			evenodd += 1
			eveneven += 1
			oddodd += 1
		print(min([oddodd, oddeven, evenodd, eveneven]))


from collections import *
from sys import stdin, stderr

def rl():
	return [int(w) for w in stdin.readline().split()]
(n, m) = rl()
if n > 3:
	print(-1)
	return
if n < 2:
	print(0)
	return
a = [[int(c) for c in stdin.readline().rstrip()] for _ in range(n)]
if n == 2:
	a.append(a[0])
r = n * m
for target in range(4):
	total = 0
	for (a0, a1, a2) in zip(*a):
		if a0 ^ a1 != target & 1 or a1 ^ a2 != target >> 1:
			total += 1
		target ^= 3
	if total < r:
		r = total
print(r)


def p(f):
	for i in range(len(f)):
		print(i, end=': ')
		for j in range(len(f[i])):
			print(int(f[i][j]), end=' ')
		print()

def build_mask(n, m, f):
	global mask
	mask1 = [[0] * n for i in range(2)]
	for i in range(1 << n):
		for j in range(1 << n):
			for k in range(n):
				mask1[0][k] = bool(i & 1 << k)
				mask1[1][k] = bool(j & 1 << k)
			(cnt1, cnt2) = (0, 0)
			cnt = mask1[0][0] + mask1[0][1] + mask1[1][0] + mask1[1][1]
			if n == 3:
				cnt2 = mask1[0][1] + mask1[0][2] + mask1[1][1] + mask1[1][2]
			if n == 3 and cnt % 2 == 1 and (cnt2 % 2 == 1):
				mask[i].append(j)
			elif n == 2 and cnt % 2 == 1:
				mask[i].append(j)

def dp(n, m, f):
	global mask
	dp = [0] * 2 ** n
	dp1 = [0] * 2 ** n
	for i in range(1 << n):
		for k in range(n):
			if bool(i & 1 << k) != bool(f[k][0]):
				dp[i] += 1
	for i in range(1, m):
		for j in range(1 << n):
			cnt = 0
			for k in range(n):
				if bool(j & 1 << k) != bool(f[k][i]):
					cnt += 1
			mini = 1 << 30
			for k in range(len(mask[j])):
				mini = min(mini, dp[int(mask[j][k])])
			dp1[j] = cnt + mini
		for j in range(1 << n):
			dp[j] = dp1[j]
	print(min(dp))
	exit()
(n, m) = map(int, input().split())
f = [[0] * max(n, m) for i in range(min(n, m))]
if n > m:
	for i in range(n):
		s = str(input())
		for j in range(m):
			f[j][i] = int(s[j])
	(n, m) = (m, n)
else:
	for i in range(n):
		s = str(input())
		for j in range(m):
			f[i][j] = int(s[j])
if min(n, m) > 3:
	print(-1)
	exit()
if min(n, m) == 1:
	print(0)
	exit()
mask = [[] for i in range(2 ** n)]
build_mask(n, m, f)
dp(n, m, f)
p(mask)


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
if n == 1 or m == 1:
	print(0)
	exit()
field = []
for _ in range(n):
	field.append([int(item) for item in input().rstrip()])
if n < m:
	(n, m) = (m, n)
	nfield = []
	for col in zip(*field):
		nfield.append(list(col))
	field = nfield[:]
nums = []
for line in field:
	val = 0
	for (i, item) in enumerate(line):
		val += item << i
	nums.append(val)
if m == 2:
	ans = n * m
	for i in range(2):
		parity = i
		diff = 0
		for (j, num) in enumerate(nums):
			if parity == 0:
				diff += min(bin(num ^ 3).count('1'), bin(num ^ 0).count('1'))
			else:
				diff += min(bin(num ^ 1).count('1'), bin(num ^ 2).count('1'))
			parity = 1 - parity
		ans = min(ans, diff)
elif m == 3:
	ans = n * m
	for i in range(2):
		parity = i
		diff = 0
		for (j, num) in enumerate(nums):
			if parity == 0:
				c1 = bin(num ^ 5).count('1')
				c2 = bin(num ^ 2).count('1')
				if c1 < c2:
					diff += c1
				else:
					diff += c2
			else:
				c1 = bin(num ^ 0).count('1')
				c2 = bin(num ^ 7).count('1')
				if c1 < c2:
					diff += c1
				else:
					diff += c2
			parity = 1 - parity
		ans = min(ans, diff)
	for i in range(2):
		parity = i
		diff = 0
		for (j, num) in enumerate(nums):
			if parity == 0:
				c1 = bin(num ^ 1).count('1')
				c2 = bin(num ^ 6).count('1')
				if c1 < c2:
					diff += c1
				else:
					diff += c2
			else:
				c1 = bin(num ^ 4).count('1')
				c2 = bin(num ^ 3).count('1')
				if c1 < c2:
					diff += c1
				else:
					diff += c2
			parity = 1 - parity
		ans = min(ans, diff)
else:
	print(-1)
	exit()
print(ans)


(n, m) = map(int, input().split())
if n > 3 and m > 3:
	print(-1)
else:
	arr = [[] for i in range(n)]
	for i in range(n):
		arr[i] = list(map(int, list(input())))
	if n < m:
		arr1 = [[0 for i in range(n)] for i in range(m)]
		for i in range(n):
			for j in range(m):
				arr1[j][i] = arr[i][j]
		arr = arr1
	if n == 1 or m == 1:
		print(0)
	elif n == 2 or m == 2:
		ans1 = 0
		for i in range(len(arr)):
			if i % 2 == 0:
				if arr[i][0] + arr[i][1] != 1:
					ans1 += 1
			elif arr[i][0] + arr[i][1] == 1:
				ans1 += 1
		ans2 = 0
		for i in range(len(arr)):
			if i % 2 == 0:
				if arr[i][0] + arr[i][1] == 1:
					ans2 += 1
			elif arr[i][0] + arr[i][1] != 1:
				ans2 += 1
		print(min(ans1, ans2))
	else:
		oo = [[0, 1, 0], [1, 0, 1]]
		oe = [[1, 0, 0], [0, 1, 1]]
		eo = [[0, 0, 1], [1, 1, 0]]
		ee = [[0, 0, 0], [1, 1, 1]]
		ans1 = 0
		for i in range(len(arr)):
			if i % 2 == 0:
				if arr[i] not in oo:
					ans1 += 1
			elif arr[i] not in ee:
				ans1 += 1
		ans2 = 0
		for i in range(len(arr)):
			if i % 2 == 0:
				if arr[i] not in oe:
					ans2 += 1
			elif arr[i] not in eo:
				ans2 += 1
		ans3 = 0
		for i in range(len(arr)):
			if i % 2 == 0:
				if arr[i] not in eo:
					ans3 += 1
			elif arr[i] not in oe:
				ans3 += 1
		ans4 = 0
		for i in range(len(arr)):
			if i % 2 == 0:
				if arr[i] not in ee:
					ans4 += 1
			elif arr[i] not in oo:
				ans4 += 1
		print(min(ans1, ans2, ans3, ans4))


import sys

def dif(x, y):
	ans = 0
	for i in range(3):
		if x % 2 != y % 2:
			ans += 1
		x //= 2
		y //= 2
	return ans

def s(x, y):
	ans = 0
	for i in range(3):
		ans += x % 2
		ans += y % 2
		x //= 2
		y //= 2
	return ans

def main():
	(n, m) = map(int, sys.stdin.readline().split())
	inf = 10 ** 9
	if n > 3:
		print(-1)
		return
	if n == 1:
		print(0)
		return
	f = [None] * n
	for i in range(n):
		f[i] = sys.stdin.readline()
	a = [0] * m
	d = [[0] * 8 for i in range(8)]
	for msk1 in range(8):
		for msk2 in range(8):
			d[msk1][msk2] = dif(msk1, msk2)
	for i in range(m):
		cur = 0
		for j in range(n):
			if f[j][i] == '1':
				cur += 2 ** j
		a[i] = cur
	if n == 2:
		dp = [[inf] * 4 for i in range(m)]
		for msk in range(2 ** 2):
			dp[0][msk] = d[msk][a[0]]
		par = []
		for msk in range(2 ** 2):
			for msk1 in range(2 ** 2):
				if s(msk, msk1) % 2 == 1:
					par.append((msk, msk1))
		for i in range(1, m):
			for (msk, msk1) in par:
				dp[i][msk] = min(dp[i][msk], dp[i - 1][msk1] + dif(msk, a[i]))
		sys.stdout.write(str(min(dp[m - 1])))
	if n == 3:
		dp = [[inf] * 8 for i in range(m)]
		for msk in range(2 ** 3):
			dp[0][msk] = d[msk][a[0]]
		par = []
		for msk in range(2 ** 3):
			for msk1 in range(2 ** 3):
				if s(msk // 2, msk1 // 2) % 2 == 1 and s(msk - msk // 4 * 4, msk1 - msk1 // 4 * 4) % 2 == 1:
					par.append((msk, msk1))
		for i in range(1, m):
			for (msk, msk1) in par:
				dp[i][msk] = min(dp[i][msk], dp[i - 1][msk1] + dif(msk, a[i]))
		sys.stdout.write(str(min(dp[m - 1])))
main()


(n, m) = map(int, input().split())
A = [list(map(int, list(input()))) for i in range(n)]

def diff3(X, i, j):
	if i == 1 and j == 1:
		k = [0, 1, 0]
	elif i == 0 and j == 1:
		k = [0, 0, 1]
	elif i == 1 and j == 0:
		k = [0, 1, 1]
	else:
		k = [0, 0, 0]
	dif = 0
	for ii in range(3):
		if X[ii] != k[ii]:
			dif += 1
	return min(dif, 3 - dif)
if n == 1 or m == 1:
	print(0)
elif n >= 4 and m >= 4:
	print(-1)
elif n == 2 or m == 2:
	if m > n:
		(m, n) = (n, m)
		B = [[0] * m for i in range(n)]
		for i in range(n):
			for j in range(m):
				B[i][j] = A[j][i]
	else:
		B = A
	ans = float('inf')
	C = [sum(B[i]) % 2 for i in range(n)]
	ans0 = 0
	p = 0
	for i in range(n):
		if C[i] != p:
			ans0 += 1
		p = (p + 1) % 2
	ans = min(ans, ans0)
	ans0 = 0
	p = 1
	for i in range(n):
		if C[i] != p:
			ans0 += 1
		p = (p + 1) % 2
	ans = min(ans, ans0)
	print(ans)
else:
	if m > n:
		(m, n) = (n, m)
		B = [[0] * m for i in range(n)]
		for i in range(n):
			for j in range(m):
				B[i][j] = A[j][i]
	else:
		B = A
	ans = float('inf')
	for i in range(2):
		for j in range(2):
			ans0 = 0
			ii = i
			jj = j
			for k in range(n):
				ans0 += diff3(B[k][:], ii, jj)
				ii = (ii + 1) % 2
				jj = (jj + 1) % 2
			ans = min(ans, ans0)
	print(ans)


from sys import stdin, exit
from bisect import bisect_left as bl, bisect_right as br
input = lambda : stdin.readline()[:-1]
intput = lambda : int(input())
sinput = lambda : input().split()
intsput = lambda : map(int, sinput())

def dprint(*args, **kwargs):
	if debugging:
		print(*args, **kwargs)
debugging = 1
(n, m) = intsput()
grid = []
for _ in range(n):
	grid.append(list(map(int, input())))
if n >= 4 and m >= 4:
	print(-1)
	exit(0)
if n == 1 or m == 1:
	print(0)
	exit(0)
if n == 2:
	odds_in_odds = 0
	evens_in_evens = 0
	for i in range(m):
		val = grid[0][i] + grid[1][i]
		if i % 2:
			if val % 2:
				odds_in_odds += 1
		elif val % 2 == 0:
			evens_in_evens += 1
	changes = odds_in_odds + evens_in_evens
	ans = min(m - changes, changes)
	print(ans)
	exit(0)
if m == 2:
	odds_in_odds = 0
	evens_in_evens = 0
	for i in range(n):
		val = grid[i][0] + grid[i][1]
		if i % 2:
			if val % 2:
				odds_in_odds += 1
		elif val % 2 == 0:
			evens_in_evens += 1
	changes = odds_in_odds + evens_in_evens
	ans = min(n - changes, changes)
	print(ans)
	exit(0)
if n == 3:
	odds_in_odds = set()
	evens_in_odds = set()
	odds_in_evens = set()
	evens_in_evens = set()
	for i in range(m):
		val = grid[0][i] + grid[1][i]
		if i % 2:
			if val % 2:
				odds_in_odds.add(i)
			else:
				evens_in_odds.add(i)
		elif val % 2 == 0:
			evens_in_evens.add(i)
		else:
			odds_in_evens.add(i)
	odds_in_odds_ = 0
	t1_odd_extra_changes = 0
	evens_in_odds_ = 0
	t2_odd_extra_changes = 0
	evens_in_evens_ = 0
	t1_even_extra_changes = 0
	odds_in_evens_ = 0
	t2_even_extra_changes = 0
	for i in range(m):
		val = grid[1][i] + grid[2][i]
		if i % 2:
			if val % 2:
				odds_in_odds_ += 1
				if i not in odds_in_odds:
					t1_odd_extra_changes += 1
			else:
				evens_in_odds_ += 1
				if i not in evens_in_odds:
					t2_odd_extra_changes += 1
		elif val % 2 == 0:
			evens_in_evens_ += 1
			if i not in evens_in_evens:
				t1_even_extra_changes += 1
		else:
			odds_in_evens_ += 1
			if i not in odds_in_evens:
				t2_even_extra_changes += 1
	a = len(odds_in_odds) + len(evens_in_evens) + t1_odd_extra_changes + t1_even_extra_changes
	b = len(odds_in_odds) + len(evens_in_evens) + evens_in_odds_ + odds_in_evens_ - t2_even_extra_changes - t2_odd_extra_changes
	c = m - len(odds_in_odds) - len(evens_in_evens) + t2_even_extra_changes + t2_odd_extra_changes
	d = m - len(odds_in_odds) - len(evens_in_evens) + odds_in_odds_ + evens_in_evens_ - t1_odd_extra_changes - t1_even_extra_changes
	print(min(a, b, c, d))
	exit(0)
if m == 3:
	odds_in_odds = set()
	evens_in_odds = set()
	odds_in_evens = set()
	evens_in_evens = set()
	for i in range(n):
		val = grid[i][0] + grid[i][1]
		if i % 2:
			if val % 2:
				odds_in_odds.add(i)
			else:
				evens_in_odds.add(i)
		elif val % 2 == 0:
			evens_in_evens.add(i)
		else:
			odds_in_evens.add(i)
	odds_in_odds_ = 0
	t1_odd_extra_changes = 0
	evens_in_odds_ = 0
	t2_odd_extra_changes = 0
	evens_in_evens_ = 0
	t1_even_extra_changes = 0
	odds_in_evens_ = 0
	t2_even_extra_changes = 0
	for i in range(n):
		val = grid[i][1] + grid[i][2]
		if i % 2:
			if val % 2:
				odds_in_odds_ += 1
				if i not in odds_in_odds:
					t1_odd_extra_changes += 1
			else:
				evens_in_odds_ += 1
				if i not in evens_in_odds:
					t2_odd_extra_changes += 1
		elif val % 2 == 0:
			evens_in_evens_ += 1
			if i not in evens_in_evens:
				t1_even_extra_changes += 1
		else:
			odds_in_evens_ += 1
			if i not in odds_in_evens:
				t2_even_extra_changes += 1
	a = len(odds_in_odds) + len(evens_in_evens) + t1_odd_extra_changes + t1_even_extra_changes
	b = len(odds_in_odds) + len(evens_in_evens) + evens_in_odds_ + odds_in_evens_ - t2_even_extra_changes - t2_odd_extra_changes
	c = n - len(odds_in_odds) - len(evens_in_evens) + t2_even_extra_changes + t2_odd_extra_changes
	d = n - len(odds_in_odds) - len(evens_in_evens) + odds_in_odds_ + evens_in_evens_ - t1_odd_extra_changes - t1_even_extra_changes
	print(min(a, b, c, d))
	exit(0)
raise Exception


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
l = []
for _ in range(n):
	l.append(input().strip())

def witch(s):
	out = 0
	if s[0] != s[1]:
		out += 2
	if s[1] != s[2]:
		out += 1
	return out
if n >= 4 and m >= 4:
	print(-1)
else:
	if n < m:
		(n, m) = (m, n)
		l = [''.join([l[j][i] for j in range(m)]) for i in range(n)]
	if m == 1:
		print(0)
	elif m == 2:
		even = 0
		odd = 0
		first = l.pop(0)
		if first == '00' or first == '11':
			odd += 1
		else:
			even += 1
		for nex in l:
			if nex == '00' or nex == '11':
				(odd, even) = (even + 1, odd)
			else:
				(odd, even) = (even, odd + 1)
		print(min(even, odd))
	elif m == 3:
		ll = [0, 0, 0, 0]
		for nex in l:
			ll.reverse()
			ll[witch(nex)] += 1
		print(n - max(ll))


mod = 10 ** 9 + 7

def solve():
	(n, m) = map(int, input().split())
	ans = 0
	s = []
	for i in range(n):
		s.append(list(input()))
	if n >= 4 and m > -4:
		ans = -1
	elif n == 1 or m == 1:
		ans = 0
	elif n == 2 or m == 2:
		vec = []
		if n == 2:
			for i in range(m):
				sm = 0
				if s[0][i] == '1':
					sm += 1
				if s[1][i] == '1':
					sm += 1
				vec.append(sm)
		else:
			for i in range(n):
				sm = 0
				if s[i][0] == '1':
					sm += 1
				if s[i][1] == '1':
					sm += 1
				vec.append(sm)
		tmp1 = 0
		tmp2 = 0
		for i in range(len(vec)):
			if vec[i] % 2 == i % 2:
				tmp1 += 1
			if (vec[i] + 1) % 2 == i % 2:
				tmp2 += 1
		ans = len(vec) - max(tmp1, tmp2)
	else:
		vec = []
		if n == 3:
			for i in range(m):
				sm1 = (1 if s[0][i] == '1' else 0) + (1 if s[1][i] == '1' else 0)
				sm2 = (1 if s[1][i] == '1' else 0) + (1 if s[2][i] == '1' else 0)
				vec.append([sm1, sm2])
		else:
			for i in range(n):
				sm1 = (1 if s[i][0] == '1' else 0) + (1 if s[i][1] == '1' else 0)
				sm2 = (1 if s[i][1] == '1' else 0) + (1 if s[i][2] == '1' else 0)
				vec.append([sm1, sm2])
		tmp = [0 for i in range(4)]
		for i in range(len(vec)):
			if vec[i][0] % 2 == vec[i][1] % 2:
				if vec[i][0] % 2 == i % 2:
					tmp[0] += 1
				else:
					tmp[1] += 1
			elif vec[i][0] % 2 == i % 2:
				tmp[2] += 1
			else:
				tmp[3] += 1
		ans = len(vec) - max(tmp)
	print(ans)
t = 1
for _ in range(t):
	solve()


from sys import stdin

def inp():
	return stdin.buffer.readline().rstrip().decode('utf8')

def itg():
	return int(stdin.buffer.readline())

def mpint():
	return map(int, stdin.buffer.readline().split())

def clockwise(two_d_array, copy=False):
	if copy:
		return list(map(list, zip(*two_d_array[::-1])))
	two_d_array[:] = map(list, zip(*two_d_array[::-1]))

def get_bit(mask: int, bit_length, index):
	return mask >> bit_length - index % bit_length - 1 & 1

def to_binary(iterable):
	result = 0
	for item in iterable:
		result <<= 1
		result += item
	return result

def mask_differ(mask1, mask2):
	if not isinstance(mask1, int):
		mask1 = to_binary(mask1)
	if not isinstance(mask2, int):
		mask2 = to_binary(mask2)
	return mask1 ^ mask2

def binary_count_1(binary_num: int):
	result = 0
	while binary_num:
		result += binary_num & 1
		binary_num >>= 1
	return result
INF = 487639487

def solve():
	(n, m) = mpint()
	g = [list(map(lambda b: b == '1', inp())) for _ in range(n)]
	if n >= 4:
		return -1
	if n == 1:
		return 0
	max_mask = 1 << n
	clockwise(g)
	(n, m) = (m, n)
	dp = [[INF] * max_mask for _ in range(n)]

	def is_good(m1, m2):
		for i in range(m - 1):
			s = get_bit(m1, m, i) + get_bit(m1, m, i + 1) + get_bit(m2, m, i) + get_bit(m2, m, i + 1)
			if s & 1 ^ 1:
				return False
		return True
	is_good_table = [[is_good(m1, m2) for m2 in range(max_mask)] for m1 in range(max_mask)]
	count_differ_table = [[binary_count_1(mask_differ(m1, m2)) for m2 in range(max_mask)] for m1 in range(max_mask)]
	mask1 = to_binary(g[0])
	for mask2 in range(max_mask):
		dp[0][mask2] = binary_count_1(mask_differ(mask1, mask2))
	for i in range(1, n):
		mask_i = to_binary(g[i])
		for mask1 in range(max_mask):
			mask1_cost = dp[i - 1][mask1]
			for mask2 in range(max_mask):
				if is_good_table[mask1][mask2]:
					mask2_cost = count_differ_table[mask_i][mask2]
					dp[i][mask2] = min(dp[i][mask2], mask1_cost + mask2_cost)
	return min(dp[-1])
print(solve())


import os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
ZERO = 48
ONE = 49
(n, m) = map(int, input().split())
MAP = []
for i in range(n):
	MAP.append(input()[:m])
if n == 1 or m == 1:
	print(0)
elif n == 2:
	numMatrix = []
	for elem in MAP:
		numMatrix.append(list(map(int, elem)))
	FirstCand = 0
	SecondCand = 0
	for i in range(m):
		numZero = (numMatrix[0][i] + numMatrix[1][i]) % 2
		FirstCand += (numZero - i) % 2
		SecondCand += (numZero - i - 1) % 2
	print(min(FirstCand, SecondCand))
elif m == 2:
	numMatrix = []
	for elem in MAP:
		numMatrix.append(list(map(int, elem)))
	FirstCand = 0
	SecondCand = 0
	for i in range(n):
		numZero = (numMatrix[i][0] + numMatrix[i][1]) % 2
		FirstCand += (numZero - i) % 2
		SecondCand += (numZero - i - 1) % 2
	print(min(FirstCand, SecondCand))
elif n == 3:
	numMatrix = []
	for elem in MAP:
		numMatrix.append(list(map(int, elem)))
	FirstCand = 0
	SecondCand = 0
	ThirdCand = 0
	FourthCand = 0
	for i in range(m):
		numZeroUp = (numMatrix[0][i] + numMatrix[1][i] - i) % 2
		numZeroDown = (numMatrix[1][i] + numMatrix[2][i] - i) % 2
		if numZeroUp == 0 and numZeroDown == 0:
			SecondCand += 1
			ThirdCand += 1
			FourthCand += 1
		elif numZeroUp == 1 and numZeroDown == 1:
			FirstCand += 1
			ThirdCand += 1
			FourthCand += 1
		elif numZeroUp == 0 and numZeroDown == 1:
			FirstCand += 1
			SecondCand += 1
			FourthCand += 1
		else:
			FirstCand += 1
			SecondCand += 1
			ThirdCand += 1
	print(min(FirstCand, SecondCand, ThirdCand, FourthCand))
elif m == 3:
	numMatrix = []
	for elem in MAP:
		numMatrix.append(list(map(int, elem)))
	FirstCand = 0
	SecondCand = 0
	ThirdCand = 0
	FourthCand = 0
	for i in range(n):
		numZeroUp = (numMatrix[i][0] + numMatrix[i][1] - i) % 2
		numZeroDown = (numMatrix[i][1] + numMatrix[i][2] - i) % 2
		if numZeroUp == 0 and numZeroDown == 0:
			SecondCand += 1
			ThirdCand += 1
			FourthCand += 1
		elif numZeroUp == 1 and numZeroDown == 1:
			FirstCand += 1
			ThirdCand += 1
			FourthCand += 1
		elif numZeroUp == 0 and numZeroDown == 1:
			FirstCand += 1
			SecondCand += 1
			FourthCand += 1
		else:
			FirstCand += 1
			SecondCand += 1
			ThirdCand += 1
	print(min(FirstCand, SecondCand, ThirdCand, FourthCand))
else:
	print(-1)


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, log
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
mod2 = 998244353

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

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

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)]
(n, m) = sp()
mat = []
for i in range(n):
	mat.append(list(map(int, data())))
if n >= 4 and m >= 4:
	out(-1)
	exit()
if n == 1 or m == 1:
	out(0)
	exit()
if n < m:
	new = [[0] * n for i in range(m)]
	for i in range(n):
		for j in range(m):
			new[j][i] = mat[i][j]
	mat = new
(n, m) = (max(n, m), min(n, m))
if m == 2:
	(t1, t2) = (0, 0)
	for i in range(n):
		temp = sum(mat[i])
		if i & 1:
			if temp & 1:
				t1 += 1
			else:
				t2 += 1
			continue
		if temp & 1:
			t2 += 1
		else:
			t1 += 1
	out(min(t1, t2))
	exit()
(t1, t2, t3, t4) = (0, 0, 0, 0)
for i in range(n):
	if i & 1:
		if sum(mat[i]) not in [0, 3]:
			t2 += 1
		if mat[i][1]:
			if mat[i][0] == mat[i][2] == 1:
				t1 += 1
			else:
				t1 += mat[i][0] + mat[i][2]
		elif mat[i][0] + mat[i][2] <= 1:
			t1 += 1
		if not mat[i][0]:
			if mat[i][1] + mat[i][2] != 2:
				t3 += 1
		elif mat[i][1] + mat[i][2] != 0:
			t3 += 1
		if not mat[i][2]:
			if mat[i][0] + mat[i][1] != 2:
				t4 += 1
		elif mat[i][0] + mat[i][1] != 0:
			t4 += 1
	else:
		if sum(mat[i]) not in [0, 3]:
			t1 += 1
		if mat[i][1]:
			if mat[i][0] == mat[i][2] == 1:
				t2 += 1
			else:
				t2 += mat[i][0] + mat[i][2]
		elif mat[i][0] + mat[i][2] <= 1:
			t2 += 1
		if not mat[i][0]:
			if mat[i][1] + mat[i][2] != 2:
				t4 += 1
		elif mat[i][1] + mat[i][2] != 0:
			t4 += 1
		if not mat[i][2]:
			if mat[i][0] + mat[i][1] != 2:
				t3 += 1
		elif mat[i][0] + mat[i][1] != 0:
			t3 += 1
out(min(t1, t2, t3, t4))


import math
import sys
import bisect
t = 1

def nsb(x):
	cnt = 0
	for i in range(n, -1, -1):
		k = x >> i
		if k & 1:
			cnt += 1
	return cnt
for _ in range(t):
	mod = 10 ** 9 + 7
	(n, m) = map(int, input().split())
	l1 = []
	l = []
	flag = True
	if min(n, m) >= 4:
		flag = False
	for i in range(n):
		l1.append(input())
	if flag:
		if min(n, m) >= 2:
			if n > 3:
				s = ''
				for j in range(m):
					s = ''
					for i in range(n):
						s += l1[i][j]
					l.append(s)
				(n1, m1) = (n, m)
				n = min(n1, m1)
				m = max(n1, m1)
			else:
				l = l1
			cval = []
			mul = 1
			prev3 = []
			prev2 = []
			prev2.append([1, 2])
			prev2.append([0, 3])
			prev2.append([3, 0])
			prev2.append([1, 2])
			prev3.append([5, 2])
			prev3.append([3, 4])
			prev3.append([0, 7])
			prev3.append([1, 6])
			prev3.append([1, 6])
			prev3.append([0, 7])
			prev3.append([3, 4])
			prev3.append([5, 2])
			for j in range(m):
				suma = 0
				mul = 1
				for i in range(n - 1, -1, -1):
					suma += mul * int(l[i][j])
					mul *= 2
				cval.append(suma)
			dp = [[0 for j in range(2 ** n)] for i in range(m)]
			for i in range(2 ** n):
				dp[0][i] = nsb(i ^ cval[0])
			for i in range(1, m):
				for j in range(2 ** n):
					if n == 2:
						dp[i][j] = min(dp[i - 1][prev2[j][0]], dp[i - 1][prev2[j][1]]) + nsb(j ^ cval[i])
					else:
						dp[i][j] = min(dp[i - 1][prev3[j][0]], dp[i - 1][prev3[j][1]]) + nsb(j ^ cval[i])
			ans = 10 ** 18
			for i in range(2 ** n):
				ans = min(ans, dp[m - 1][i])
			print(ans)
		else:
			print(0)
	else:
		print(-1)


from math import inf
import sys
input = sys.stdin.readline

def print(val):
	sys.stdout.write(str(val) + '\n')

def prog():
	(n, m) = map(int, input().split())
	if n >= 4 and m >= 4:
		print(-1)
	elif n == 1 or m == 1:
		print(0)
	else:
		grid = [list(input().strip()) for i in range(n)]
		if m < n:
			grid2 = [[0] * n for i in range(m)]
			for i in range(n):
				for j in range(m):
					grid2[j][i] = grid[i][j]
			(m, n) = (n, m)
			grid = grid2
		num_masks = 2 ** n
		masks = []
		for i in range(num_masks):
			masks.append(bin(i)[:1:-1] + '0' * (n - len(bin(i)[:1:-1])))
		if n == 2:
			works = {0: (1, 2), 1: (0, 3), 2: (0, 3), 3: (1, 2)}
		elif n == 3:
			works = {0: (5, 2), 1: (3, 4), 2: (0, 7), 3: (1, 6), 4: (1, 6), 5: (0, 7), 6: (3, 4), 7: (5, 2)}
		dp = [[inf] * num_masks for _ in range(m)]
		for i in range(num_masks):
			dp[0][i] = 0
			for j in range(n):
				dp[0][i] += grid[j][0] != masks[i][j]
		for i in range(1, m):
			for mask in range(num_masks):
				diff = 0
				for j in range(n):
					diff += grid[j][i] != masks[mask][j]
				for prev_mask in works[mask]:
					dp[i][mask] = min(dp[i][mask], dp[i - 1][prev_mask] + diff)
		mn_change = inf
		for mask in range(num_masks):
			mn_change = min(mn_change, dp[m - 1][mask])
		print(mn_change)
prog()


import os, sys
from io import BytesIO, IOBase

def main():
	(n, m) = map(int, input().split())
	arr = [list(input().strip()) for _ in range(n)]
	if n >= 4 and m >= 4:
		print(-1)
	elif n == 1 or m == 1:
		print(0)
	else:
		ans = 10 ** 10
		if m == 3 or n == 3:
			pos = ['000', '100', '010', '001', '110', '101', '011', '111']
			if m == 3:
				for i in pos:
					fin = (arr[0][0] == i[0]) + (arr[0][1] == i[1]) + (arr[0][2] == i[2])
					(fis, sec) = ((int(i[0]) + int(i[1]) + 1) % 2, (int(i[1]) + int(i[2]) + 1) % 2)
					for j in range(1, n):
						s = 0
						if (int(arr[j][0]) + int(arr[j][1])) % 2 != fis:
							s += 1
						if (int(arr[j][1]) + int(arr[j][2])) % 2 != sec:
							s += 1
						if s == 2:
							s -= 1
						fin += s
						fis ^= 1
						sec ^= 1
					ans = min(ans, fin)
			elif n == 3:
				for i in pos:
					fin = (arr[0][0] == i[0]) + (arr[1][0] == i[1]) + (arr[2][0] == i[2])
					(fis, sec) = ((int(i[0]) + int(i[1]) + 1) % 2, (int(i[1]) + int(i[2]) + 1) % 2)
					for j in range(1, m):
						s = 0
						if (int(arr[0][j]) + int(arr[1][j])) % 2 != fis:
							s += 1
						if (int(arr[1][j]) + int(arr[2][j])) % 2 != sec:
							s += 1
						if s == 2:
							s -= 1
						fin += s
						fis ^= 1
						sec ^= 1
					ans = min(ans, fin)
		elif m == 2 or n == 2:
			pos = ['00', '10', '01', '11']
			if m == 2:
				for i in pos:
					fin = (arr[0][0] == i[0]) + (arr[0][1] == i[1])
					fis = (int(i[0]) + int(i[1]) + 1) % 2
					for j in range(1, n):
						s = 0
						if (int(arr[j][0]) + int(arr[j][1])) % 2 != fis:
							s += 1
						fin += s
						fis ^= 1
					ans = min(ans, fin)
			elif n == 2:
				for i in pos:
					fin = (arr[0][0] == i[0]) + (arr[1][0] == i[1])
					fis = (int(i[0]) + int(i[1]) + 1) % 2
					for j in range(1, m):
						s = 0
						if (int(arr[0][j]) + int(arr[1][j])) % 2 != fis:
							s += 1
						fin += s
						fis ^= 1
					ans = min(ans, fin)
		print(ans)
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()


def solve_two(A, n, m):
	B = [(A[0][i] + A[1][i]) % 2 for i in range(m)]
	odd = 0
	even = 0
	for i in range(m):
		if B[i] == i % 2:
			odd += 1
		else:
			even += 1
	return min(odd, even)

def solve_three(A, n, m):
	BU = [(A[0][i] + A[1][i]) % 2 for i in range(m)]
	BD = [(A[1][i] + A[2][i]) % 2 for i in range(m)]
	oddodd = 0
	oddeven = 0
	evenodd = 0
	eveneven = 0
	for i in range(m):
		if BU[i] == i % 2:
			oddeven += 1
			oddodd += 1
		else:
			eveneven += 1
			evenodd += 1
		if BD[i] == i % 2:
			if BU[i] == i % 2:
				evenodd += 1
			else:
				oddodd += 1
		elif BU[i] == i % 2:
			eveneven += 1
		else:
			oddeven += 1
	return min([oddodd, oddeven, evenodd, eveneven])

def solve():
	(n, m) = map(int, input().split())
	A = [list(map(int, list(input()))) for _ in range(n)]
	if n >= 4 and m >= 4:
		return -1
	if n == 1:
		return 0
	if n > m:
		(n, m) = (m, n)
		A = list(zip(*A))
	ans = 0
	if n == 2:
		return solve_two(A, n, m)
	if n == 3:
		return solve_three(A, n, m)

def main():
	print(solve())
main()


import sys, math
import io, os
from bisect import bisect_left as bl, bisect_right as br, insort
from heapq import heapify, heappush, heappop
from collections import defaultdict as dd, deque, Counter

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

def mdata():
	return list(map(int, data().split()))

def outl(var):
	sys.stdout.write(' '.join(map(str, var)) + '\n')

def out(var):
	sys.stdout.write(str(var) + '\n')
from decimal import Decimal
from fractions import Fraction
INF = float('inf')
mod = int(1000000000.0) + 7
(n, m) = mdata()
mat = [data() for i in range(n)]
if n > 3 and m > 3:
	out(-1)
	exit()
elif n == 1 or m == 1:
	out(0)
	exit()
if n > m:
	mat1 = [[0] * n for i in range(m)]
	for i in range(n):
		for j in range(m):
			mat1[j][i] = int(mat[i][j])
	mat = mat1
	(n, m) = (m, n)
else:
	mat1 = [[0] * m for i in range(n)]
	for i in range(n):
		for j in range(m):
			mat1[i][j] = int(mat[i][j])
	mat = mat1
if n == 2 or m == 2:
	(o1, o2) = (0, 0)
	for i in range(m):
		if (mat[0][i] + mat[1][i]) % 2 == 1:
			if i % 2 == 0:
				o2 += 1
			else:
				o1 += 1
		elif i % 2 == 0:
			o1 += 1
		else:
			o2 += 1
	out(min(o1, o2))
else:
	(o1, o2) = ([], [])
	for i in range(m):
		if (mat[0][i] + mat[1][i]) % 2 == 1:
			if i % 2 == 0:
				o2.append(i)
			else:
				o1.append(i)
		elif i % 2 == 0:
			o1.append(i)
		else:
			o2.append(i)
	(o4, o3) = ([], [])
	for i in range(m):
		if (mat[2][i] + mat[1][i]) % 2 == 1:
			if i % 2 == 0:
				o4.append(i)
			else:
				o3.append(i)
		elif i % 2 == 0:
			o3.append(i)
		else:
			o4.append(i)
	out(min(len(set(o1 + o3)), len(set(o1 + o4)), len(set(o2 + o3)), len(set(o2 + o4))))


import sys
int1 = lambda x: int(x) - 1
p2D = lambda x: print(*x, sep='\n')

def II():
	return int(sys.stdin.readline())

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

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

def LLI(rows_number):
	return [LI() for _ in range(rows_number)]

def SI():
	return sys.stdin.readline()[:-1]
inf = 10 ** 16
(h, w) = MI()
aa = [SI() for _ in range(h)]
if h > 3:
	print(-1)
	exit()
if h == 1:
	print(0)
	exit()
aa = [int(''.join(row), 2) for row in zip(*aa)]

def solve(to):
	dp = [[inf] * (1 << h) for _ in range(w + 1)]
	for s in range(1 << h):
		dp[0][s] = 0
	for (i, a) in enumerate(aa):
		for s in range(1 << h):
			pre = dp[i][s]
			if pre == inf:
				continue
			for ns in to[s]:
				dp[i + 1][ns] = min(dp[i + 1][ns], pre + popcnt[a ^ ns])
	return min(dp[w])
to2 = [[1, 2], [0, 3], [0, 3], [1, 2]]
to3 = [[2, 5], [3, 4], [0, 7], [1, 6], [1, 6], [0, 7], [3, 4], [2, 5]]
popcnt = [bin(i).count('1') for i in range(8)]
if h == 2:
	print(solve(to2))
if h == 3:
	print(solve(to3))


import collections
(n, m) = map(int, input().split())
a = []
for _ in range(n):
	a.append(input())
d = {}
d[0, 0] = ['000', '111']
d[0, 1] = ['001', '110']
d[1, 0] = ['011', '100']
d[1, 1] = ['010', '101']

def solve2h(p):
	ans = 0
	for j in range(m):
		tp = (int(a[0][j]) + int(a[1][j])) % 2
		if tp != p:
			ans += 1
		p = 1 - p
	return ans

def solve2v(p):
	ans = 0
	for i in range(n):
		tp = (int(a[i][0]) + int(a[i][1])) % 2
		if tp != p:
			ans += 1
		p = 1 - p
	return ans
p = collections.defaultdict(list)

def fillh():
	pa = [(0, 0), (0, 1), (1, 0), (1, 1)]
	for j in range(m):
		for (p1, p2) in pa:
			mini = 3
			for s in d[p1, p2]:
				temp = 0
				for i in range(3):
					if s[i] != a[i][j]:
						temp += 1
				mini = min(mini, temp)
			p[p1, p2].append(mini)

def fillv():
	pa = [(0, 0), (0, 1), (1, 0), (1, 1)]
	for i in range(n):
		for (p1, p2) in pa:
			mini = 3
			for s in d[p1, p2]:
				temp = 0
				for j in range(3):
					if s[j] != a[i][j]:
						temp += 1
				mini = min(mini, temp)
			p[p1, p2].append(mini)

def solve3h(p1, p2):
	ans = 0
	for j in range(m):
		ans += p[p1, p2][j]
		p1 = 1 - p1
		p2 = 1 - p2
	return ans

def solve3v(p1, p2):
	ans = 0
	for i in range(n):
		ans += p[p1, p2][i]
		p1 = 1 - p1
		p2 = 1 - p2
	return ans
ans = 0
if min(n, m) >= 4:
	print('-1')
elif min(n, m) == 1:
	print('0')
elif min(n, m) == 2:
	if n == 2:
		ans = solve2h(0)
		ans = min(ans, solve2h(1))
	else:
		ans = solve2v(0)
		ans = min(ans, solve2v(1))
	print(ans)
else:
	if n == 3:
		fillh()
		ans = solve3h(0, 0)
		ans = min(ans, solve3h(0, 1))
		ans = min(ans, solve3h(1, 0))
		ans = min(ans, solve3h(1, 1))
	else:
		fillv()
		ans = solve3v(0, 0)
		ans = min(ans, solve3v(0, 1))
		ans = min(ans, solve3v(1, 0))
		ans = min(ans, solve3v(1, 1))
	print(ans)


import os
import sys
from io import BytesIO, IOBase
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')

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 flip(eq):
	count = []
	for i in range(2):
		for j in range(2):
			count.append(sum((eq[x][0] == (i + x) % 2 or eq[x][1] == (j + x) % 2 for x in range(len(eq)))))
	return min([x for x in count])

def solve():
	(N, M) = getInts()
	if N < 2 or N > 3:
		for n in range(N):
			input()
		if N == 1:
			return 0
		return -1
	grid = []
	for n in range(N):
		grid.append(getStr())
	if N == 2:
		eq = list((grid[0][i] == grid[1][i] for i in range(M)))
		tmp = sum((eq[i] == i % 2 for i in range(M)))
		return min(tmp, M - tmp)
	if N == 3:
		eq = []
		for j in range(M):
			eq.append((grid[0][j] == grid[1][j], grid[1][j] == grid[2][j]))
		return flip(eq)
print(solve())


import sys
import math
import collections
import heapq
import decimal

def f(l, a):
	(i, c) = (0, 0)
	for x in l:
		c += x not in a[i]
		i = (i + 1) % 2
	return c

def g(l, m):
	return min([f(l, m[i]) for i in range(len(m))])

def two():
	l = [x[0] + x[1] for x in zip(input(), input())]
	m = ([['00', '11'], ['10', '01']], [['10', '01'], ['00', '11']])
	return g(l, m)

def three():
	l = [x[0] + x[1] + x[2] for x in zip(input(), input(), input())]
	m = ([['100', '011'], ['110', '001']], [['110', '001'], ['100', '011']], [['111', '000'], ['010', '101']], [['010', '101'], ['000', '111']])
	return g(l, m)
(n, m) = (int(i) for i in input().split())
if n == 1:
	print(0)
elif n == 2:
	print(two())
elif n == 3:
	print(three())
else:
	print(-1)


(n, m) = list(map(int, input().split()))
if n >= 4 and m >= 4:
	print(-1)
elif n <= 1 or m <= 1:
	print(0)
else:
	matrix = []
	for _ in range(n):
		matrix.append(input())
	if n > 3:
		matrix2 = []
		for j in range(m):
			row = []
			for i in range(n):
				row.append(matrix[i][j])
			matrix2.append(row)
		matrix = matrix2
		temp = n
		n = m
		m = temp
	binaries = []
	changes = []
	for i in range(n - 1):
		binary = []
		change = []
		bit = 0
		for j in range(m):
			parity = int(matrix[i][j]) ^ int(matrix[i + 1][j])
			binary.append(parity)
			change.append(parity ^ bit)
			bit = 1 - bit
		binaries.append(binary)
		changes.append(change)
	if n == 2:
		total = sum(changes[0])
		print(min(total, m - total))
	else:
		total = [0] * 4
		for i in range(m):
			total[0] += changes[0][i] | changes[1][i]
			total[1] += changes[0][i] | 1 - changes[1][i]
			total[2] += 1 - changes[0][i] | changes[1][i]
			total[3] += 1 - changes[0][i] | 1 - changes[1][i]
		print(min(total))


from sys import stdin, stdout

def five_O_five(n, m, a_2d):
	if n > 3:
		return -1
	if n == 1:
		return 0
	MAX = 10 ** 9
	if n == 2:
		preMask = [0, 0, 0, 0]
		for i in range(m):
			curMask = [MAX, MAX, MAX, MAX]
			for j in range(4):
				val = ord(a_2d[0][i]) - ord('0') + 2 * (ord(a_2d[1][i]) - ord('0'))
				cnt = 0
				for k in range(2):
					if j >> k & 1 != val >> k & 1:
						cnt += 1
				for k in range(4):
					bits = (j & 1) + (j >> 1 & 1) + (k & 1) + (k >> 1 & 1)
					if bits % 2 == 1:
						curMask[j] = min(curMask[j], preMask[k] + cnt)
			preMask = curMask
		return min(preMask)
	else:
		preMask = [0, 0, 0, 0, 0, 0, 0, 0]
		for i in range(m):
			curMask = [MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX]
			for j in range(8):
				val = ord(a_2d[0][i]) - ord('0') + 2 * (ord(a_2d[1][i]) - ord('0')) + 4 * (ord(a_2d[2][i]) - ord('0'))
				cnt = 0
				for k in range(3):
					if j >> k & 1 != val >> k & 1:
						cnt += 1
				for k in range(8):
					bits_up = (j & 1) + (j >> 1 & 1) + (k & 1) + (k >> 1 & 1)
					bits_down = (j >> 1 & 1) + (j >> 2 & 1) + (k >> 1 & 1) + (k >> 2 & 1)
					if bits_up % 2 == 1 and bits_down % 2 == 1:
						curMask[j] = min(curMask[j], preMask[k] + cnt)
			preMask = curMask
		return min(preMask)
(n, m) = map(int, stdin.readline().split())
a_2d = []
for _ in range(n):
	a_2d.append(stdin.readline().strip())
stdout.write(str(five_O_five(n, m, a_2d)) + '\n')


(n, m) = map(int, input().split())
mat = []
for i in range(n):
	p = list(map(int, input()))
	mat.append(p)
if min(n, m) >= 4:
	print(-1)
if min(n, m) == 1:
	print(0)
if n == 2 or m == 2:
	p1 = 0
	p2 = 0
	temp1 = min(n, m)
	temp2 = max(n, m)
	n = temp1
	m = temp2
	for i in range(m):
		s = (mat[0][i] + mat[1][i]) % 2
		if s == i % 2:
			p1 += 1
		elif s == (i + 1) % 2:
			p2 += 1
	p = max(p1, p2)
	print(m - p)
if n == 3 or m == 3:
	ans = [[] for i in range(max(n, m))]
	temp1 = min(n, m)
	temp2 = max(n, m)
	n = temp1
	m = temp2
	for i in range(m):
		(x1, x2) = (0, 0)
		x1a = [0, 0, 0]
		x2a = [1, 1, 1]
		for j in range(3):
			if mat[j][i] == x2a[j]:
				x1 += 1
			elif mat[j][i] == x1a[j]:
				x2 += 1
		ans[i].append(min(x1, x2))
	for i in range(m):
		(x1, x2) = (0, 0)
		x1a = [0, 0, 1]
		x2a = [1, 1, 0]
		for j in range(3):
			if mat[j][i] == x2a[j]:
				x1 += 1
			elif mat[j][i] == x1a[j]:
				x2 += 1
		ans[i].append(min(x1, x2))
	for i in range(m):
		(x1, x2) = (0, 0)
		x1a = [0, 1, 1]
		x2a = [1, 0, 0]
		for j in range(3):
			if mat[j][i] == x2a[j]:
				x1 += 1
			elif mat[j][i] == x1a[j]:
				x2 += 1
		ans[i].append(min(x1, x2))
	for i in range(m):
		(x1, x2) = (0, 0)
		x1a = [1, 0, 1]
		x2a = [0, 1, 0]
		for j in range(3):
			if mat[j][i] == x2a[j]:
				x1 += 1
			elif mat[j][i] == x1a[j]:
				x2 += 1
		ans[i].append(min(x1, x2))
	(s1, s2, s3, s4) = (0, 0, 0, 0)
	for i in range(m):
		if i % 2 == 0:
			s1 += ans[i][0]
			s3 += ans[i][1]
			s2 += ans[i][3]
			s4 += ans[i][2]
		else:
			s1 += ans[i][3]
			s3 += ans[i][2]
			s2 += ans[i][0]
			s4 += ans[i][1]
	print(min(s1, s2, s3, s4))


import sys

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

def ri():
	return int(sys.stdin.readline())

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

def ws(s):
	sys.stdout.write(s)
	sys.stdout.write('\n')

def wi(n):
	sys.stdout.write(str(n))
	sys.stdout.write('\n')

def wia(a, sep=' '):
	sys.stdout.write(sep.join([str(x) for x in a]))
	sys.stdout.write('\n')

def bit_count(n):
	cnt = 0
	while n > 0:
		cnt += 1
		n = n & n - 1
	return cnt

def ok(n, mask1, mask2):
	for i in range(n - 1):
		cnt = (1 if mask1 & 1 << i else 0) + (1 if mask2 & 1 << i else 0) + (1 if mask1 & 1 << i + 1 else 0) + (1 if mask2 & 1 << i + 1 else 0)
		if cnt % 2 == 0:
			return False
	return True

def solve(n, m, a):
	if n == 1:
		return 0
	if n >= 4:
		return -1
	p2 = 2 ** n
	inf = float('inf')
	b = [0] * m
	for j in range(m):
		mask = 0
		for i in range(n):
			if a[i][j] == 1:
				mask |= 1 << i
		b[j] = mask
	dp = [[inf] * p2 for _ in range(m)]
	for mask in range(p2):
		dp[0][mask] = bit_count(b[0] ^ mask)
	masks = [[] for _ in range(p2)]
	for mask1 in range(p2):
		for mask2 in range(p2):
			if ok(n, mask1, mask2):
				masks[mask1].append(mask2)
	for i in range(1, m):
		for prev_mask in range(p2):
			for next_mask in masks[prev_mask]:
				dp[i][next_mask] = min(dp[i][next_mask], dp[i - 1][prev_mask] + bit_count(b[i] ^ next_mask))
	return min(dp[-1])

def main():
	(n, m) = ria()
	a = []
	for i in range(n):
		a.append([int(si) for si in rs()])
	wi(solve(n, m, a))
main()


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
a = [[int(j) for j in input()[:-1]] for i in range(n)]
if n >= 4 and m >= 4:
	print(-1)
	exit()
if n == 1 or m == 1:
	print(0)
	exit()
inf = 10000000000000
if n == 2 or m == 2:
	bitcheck = [[0] * 4 for i in range(4)]
	for j in range(4):
		for k in range(4):
			for i in range(1):
				if ((j >> i & 1) + (k >> i & 1) + (j >> i + 1 & 1) + (k >> i + 1 & 1)) % 2 == 0:
					bitcheck[j][k] = False
					break
			else:
				bitcheck[j][k] = True
	bitcalc = [[0] * 4 for i in range(4)]
	for j in range(4):
		for k in range(4):
			for i in range(2):
				if j >> i & 1 ^ k >> i & 1:
					bitcalc[j][k] += 1
	if n == 2:
		(n, m) = (m, n)
		b = [list(x) for x in zip(*a)]
	else:
		b = [i for i in a]
	dp = [[inf] * 4 for i in range(n)]
	for i in range(n):
		if i != 0:
			for j in range(4):
				for k in range(4):
					if bitcheck[j][k]:
						dp[i][k] = min(dp[i][k], dp[i - 1][j] + bitcalc[b[i][0] + b[i][1] * 2][k])
		else:
			for k in range(4):
				dp[i][k] = bitcalc[b[i][0] + b[i][1] * 2][k]
	print(min(dp[n - 1]))
	exit()
if n == 3 or m == 3:
	bitcheck = [[0] * 8 for i in range(8)]
	for j in range(8):
		for k in range(8):
			for i in range(2):
				if ((j >> i & 1) + (k >> i & 1) + (j >> i + 1 & 1) + (k >> i + 1 & 1)) % 2 == 0:
					bitcheck[j][k] = False
					break
			else:
				bitcheck[j][k] = True
	bitcalc = [[0] * 8 for i in range(8)]
	for j in range(8):
		for k in range(8):
			for i in range(3):
				if j >> i & 1 ^ k >> i & 1:
					bitcalc[j][k] += 1
	if n == 3:
		(n, m) = (m, n)
		b = [list(x) for x in zip(*a)]
	else:
		b = [i for i in a]
	dp = [[inf] * 8 for i in range(n)]
	for i in range(n):
		if i != 0:
			for j in range(8):
				for k in range(8):
					if bitcheck[j][k]:
						dp[i][k] = min(dp[i][k], dp[i - 1][j] + bitcalc[b[i][0] + b[i][1] * 2 + b[i][2] * 4][k])
		else:
			for k in range(8):
				dp[i][k] = bitcalc[b[i][0] + b[i][1] * 2 + b[i][2] * 4][k]
	print(min(dp[n - 1]))
	exit()


(n, m) = map(int, input().split())
if n == 1 or m == 1:
	for i in range(n):
		input()
	print(0)
elif n >= 4 and m >= 4:
	for i in range(n):
		input()
	print(-1)
else:
	matrix = []
	for i in range(n):
		row = input()
		matrix.append([])
		for j in range(m):
			matrix[-1].append(int(row[j]))
	if n == 2:
		counter = 0
		redmat = [[0] * m for k in range(n - 1)]
		for i in range(n - 1):
			for j in range(m):
				redmat[i][j] = (matrix[i][j] + matrix[i + 1][j]) % 2
				if redmat[i][j] == j % 2:
					counter += 1
		print(min(counter, m - counter))
	elif m == 2:
		counter = 0
		redmat = [[0] * m - 1 for k in range(n)]
		for j in range(m - 1):
			for i in range(n):
				redmat[i][j] = (matrix[i][j] + matrix[i][j + 1]) % 2
				if redmat[i][j] == i % 2:
					counter += 1
		print(min(counter, m - counter))
	elif n == 3:
		counteree = 0
		counteroo = 0
		countereo = 0
		redmat = [[0] * m for k in range(n - 1)]
		for i in range(n - 1):
			for j in range(m):
				redmat[i][j] = (matrix[i][j] + matrix[i + 1][j]) % 2
		for j in range(m):
			if redmat[0][j] == j % 2 and redmat[1][j] == j % 2:
				counteree += 1
			if redmat[0][j] == (j + 1) % 2 and redmat[1][j] == (j + 1) % 2:
				counteroo += 1
			if redmat[0][j] == j % 2 and redmat[1][j] == (j + 1) % 2:
				countereo += 1
		print(min(m - counteree, m - counteroo, m - countereo, counteree + counteroo + countereo))
	elif m == 3:
		counteree = 0
		counteroo = 0
		countereo = 0
		redmat = [[0] * m - 1 for k in range(n)]
		for j in range(m - 1):
			for i in range(n):
				redmat[i][j] = (matrix[i][j] + matrix[i][j + 1]) % 2
		for i in range(n):
			if redmat[i][0] == i % 2 and redmat[i][1] == i % 2:
				counteree += 1
			if redmat[i][0] == (i + 1) % 2 and redmat[i][1] == (i + 1) % 2:
				counteroo += 1
			if redmat[i][0] == i % 2 and redmat[i][1] == (i + 1) % 2:
				countereo += 1
		print(min(m - counteree, m - counteroo, m - countereo, counteree + counteroo + countereo))


(n, m) = map(int, input().split())
mat = []
for i in range(n):
	mat.append([bool(int(i)) for i in input()])
if n >= 4 and m >= 4:
	print(-1)
	exit(0)
if n == 1 or m == 1:
	print(0)
	exit(0)
if n > m:
	(m, n) = (n, m)
	mat = [[i[j] for i in mat] for j in range(len(mat[0]))]
if n == 2:
	res = []
	for (i, ni) in enumerate(mat[0]):
		if i == 0:
			continue
		if mat[0][i] + mat[1][i] + mat[0][i - 1] + mat[1][i - 1] & 1:
			res.append(True)
		else:
			res.append(False)
	ans = 0
	status = False
	l = 0
	pat1 = []
	for i in res:
		pat1.append(status)
		l += 1
		if not i:
			if status:
				ans += l
				status = False
			else:
				status = True
			l = 0
	pat1.append(status)
	if status:
		ans += l + 1
	print(min(ans, len(res) + 1 - ans))
elif n == 3:
	res = []
	for (i, ni) in enumerate(mat[0]):
		if i == 0:
			continue
		if mat[0][i] + mat[1][i] + mat[0][i - 1] + mat[1][i - 1] & 1:
			res.append(True)
		else:
			res.append(False)
	ress = []
	for (i, ni) in enumerate(mat[0]):
		if i == 0:
			continue
		if mat[1][i] + mat[2][i] + mat[1][i - 1] + mat[2][i - 1] & 1:
			ress.append(True)
		else:
			ress.append(False)
	status = False
	l = 0
	pat1 = []
	for i in res:
		pat1.append(status)
		l += 1
		if not i:
			if status:
				status = False
			else:
				status = True
			l = 0
	pat1.append(status)
	status = False
	l = 0
	pat2 = []
	for i in ress:
		pat2.append(status)
		l += 1
		if not i:
			if status:
				status = False
			else:
				status = True
			l = 0
	pat2.append(status)
	ans = len(pat1)
	a1 = 0
	a2 = 0
	a3 = 0
	a4 = 0
	for i in range(len(pat1)):
		if pat1[i] == True and pat2[i] == True:
			a1 += 1
		elif pat1[i] == True and pat2[i] == False:
			a2 += 1
		elif pat1[i] == False and pat2[i] == True:
			a3 += 1
		else:
			a4 += 1
	ans = ans - max(a1, a2, a3, a4)
	print(ans)


import collections
import math

def valid(x):
	for i in range(len(x) - 1):
		for j in range(len(x[i]) - 1):
			if (x[i][j] + x[i][j + 1] + x[i + 1][j] + x[i + 1][j + 1]) % 2 == 0:
				return False
	return True

def main():
	(n, m) = list(map(int, input().split()))
	if n >= 4 and m >= 4:
		print(-1)
		return
	a = tuple((tuple(map(int, input())) for _ in range(n)))
	if n < m:
		(n, m) = (m, n)
		a = tuple(zip(*a))
	if m == 1:
		print(0)
		return
	if m == 2:
		choices = [(0, 0), (0, 1), (1, 0), (1, 1)]
	else:
		choices = [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
	prev = []
	for c in choices:
		prev.append([i for (i, p) in enumerate(choices) if valid([p, c])])
	cost = [[sum((i != j for (i, j) in zip(r, c))) for r in choices] for c in choices]
	best = [0 for _ in choices]
	for i in a:
		i = choices.index(i)
		new = []
		for j in range(len(choices)):
			new.append(cost[i][j] + min((best[p] for p in prev[j])))
		best = new
	print(min(best))
main()


import sys
input = sys.stdin.readline
size = input()[:-1].split(' ')
size[0] = int(size[0])
size[1] = int(size[1])
lines = []

def diffOddDouble(bitList):
	flipCount = []
	for x in range(2):
		for y in range(2):
			flipCount.append(sum((bitList[i][0] == (i + x) % 2 or bitList[i][1] == (i + y) % 2 for i in range(len(bitList)))))
	return min((x for x in flipCount))
if size[0] >= 4 and size[1] >= 4:
	print(-1)
elif 1 in size:
	print(0)
elif 2 in size:
	if size[0] == 2:
		lines.append(input()[:-1])
		lines.append(input()[:-1])
		parity = list((lines[0][x] == lines[1][x] for x in range(size[1])))
	else:
		parity = []
		for x in range(size[0]):
			line = input()
			parity.append(line[0] == line[1])
	modify = sum((parity[x] == x % 2 for x in range(size[1])))
	if modify > size[1] // 2:
		modify = size[1] - modify
	print(modify)
else:
	parity = []
	if size[0] == 3:
		lines = [input()[:-1], input()[:-1], input()[:-1]]
		for x in range(size[1]):
			parity.append([lines[0][x] == lines[1][x], lines[1][x] == lines[2][x]])
	else:
		for x in range(size[0]):
			line = input()
			parity.append([lines[x][0] == lines[x][1], lines[x][1] == lines[x][2]])
	print(diffOddDouble(parity))


import time, math as mt, bisect, sys
from sys import stdin, stdout
from collections import deque
from fractions import Fraction
from collections import Counter
from collections import OrderedDict
pi = 3.141592653589793

def II():
	return int(stdin.readline())

def IO():
	return stdin.readline()

def IP():
	return map(int, stdin.readline().split())

def L():
	return list(map(int, stdin.readline().split()))

def P(x):
	return stdout.write(str(x) + '\n')

def PI(x, y):
	return stdout.write(str(x) + ' ' + str(y) + '\n')

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

def gcd(a, b):
	if a == 0:
		return b
	elif b == 0:
		return a
	if a > b:
		return gcd(a % b, b)
	else:
		return gcd(a, b % a)

def readTree():
	v = int(input())
	adj = [set() for i in range(v + 1)]
	for i in range(v - 1):
		(u1, u2) = In()
		adj[u1].add(u2)
		adj[u2].add(u1)
	return (adj, v)

def bfs(adj, v):
	visited = [False] * (v + 1)
	q = deque()
	while q:
		pass

def sieve():
	li = [True] * 1000001
	(li[0], li[1]) = (False, False)
	for i in range(2, len(li), 1):
		if li[i] == True:
			for j in range(i * i, len(li), i):
				li[j] = False
	prime = []
	for i in range(1000001):
		if li[i] == True:
			prime.append(i)
	return prime

def setBit(n):
	count = 0
	while n != 0:
		n = n & n - 1
		count += 1
	return count
mx = 10 ** 7
spf = [mx] * (mx + 1)

def SPF():
	spf[1] = 1
	for i in range(2, mx + 1):
		if spf[i] == mx:
			spf[i] = i
			for j in range(i * i, mx + 1, i):
				if i < spf[j]:
					spf[j] = i
	return
mod = 10 ** 9 + 7

def solver(msk, dp, m, n, matrix):
	for j in range(m):
		s = ''
		for i in range(n):
			s += matrix[i][j]
		val = int(s, 2)
		for i in range(2 ** n):
			for ele in msk[i]:
				changes = setBit(ele ^ val)
				dp[j + 1][i] = min(dp[j + 1][i], dp[j][ele] + changes)
	return

def solve():
	(n, m) = IP()
	matrix = [input() for i in range(n)]
	if n > 3:
		P(-1)
		return
	elif n == 1:
		P(0)
		return
	else:
		msk2 = [[1, 2], [0, 3], [0, 3], [1, 2]]
		msk3 = [[2, 5], [3, 4], [0, 7], [1, 6], [1, 6], [0, 7], [3, 4], [2, 5]]
		dp = [[1000000000.0 for i in range(2 ** n)] for j in range(m + 1)]
		for i in range(2 ** n):
			dp[0][i] = 0
		if n == 2:
			solver(msk2, dp, m, n, matrix)
		else:
			solver(msk3, dp, m, n, matrix)
		ans = 1000000000.0
		for i in range(2 ** n):
			ans = min(ans, dp[m][i])
		P(ans)
		return
t = 1
for i in range(t):
	solve()


from collections import defaultdict
con = 10 ** 9 + 7
INF = float('inf')

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

def main():
	(N, M) = getlist()
	if N >= 4 and M >= 4:
		print(-1)
		return
	if N == 1 or M == 1:
		print(0)
		return
	S = []
	for i in range(N):
		s = list(map(int, list(input())))
		S.append(s)
	if N == 2:
		L = [0] * M
		for i in range(M):
			L[i] = (S[0][i] + S[1][i]) % 2
		ans = INF
		val = 0
		for i in range(M):
			if i % 2 == 0:
				if L[i] % 2 == 0:
					val += 1
			elif L[i] % 2 == 1:
				val += 1
		ans = min(ans, val)
		val = 0
		for i in range(M):
			if i % 2 == 0:
				if L[i] % 2 == 1:
					val += 1
			elif L[i] % 2 == 0:
				val += 1
		ans = min(ans, val)
		print(ans)
		return
	else:
		DP = [[INF] * 8 for i in range(M)]
		for i in range(2):
			for j in range(2):
				for k in range(2):
					DP[0][4 * i + 2 * j + k] = (S[0][0] ^ i) + (S[1][0] ^ j) + (S[2][0] ^ k)
		for x in range(1, M):
			for i in range(2):
				for j in range(2):
					for k in range(2):
						itr = 4 * i + 2 * j + k
						if itr == 0:
							DP[x][itr] = min(DP[x - 1][2], DP[x - 1][5]) + (S[0][x] ^ 0) + (S[1][x] ^ 0) + (S[2][x] ^ 0)
						elif itr == 1:
							DP[x][itr] = min(DP[x - 1][3], DP[x - 1][4]) + (S[0][x] ^ 0) + (S[1][x] ^ 0) + (S[2][x] ^ 1)
						elif itr == 2:
							DP[x][itr] = min(DP[x - 1][0], DP[x - 1][7]) + (S[0][x] ^ 0) + (S[1][x] ^ 1) + (S[2][x] ^ 0)
						elif itr == 3:
							DP[x][itr] = min(DP[x - 1][1], DP[x - 1][6]) + (S[0][x] ^ 0) + (S[1][x] ^ 1) + (S[2][x] ^ 1)
						elif itr == 4:
							DP[x][itr] = min(DP[x - 1][1], DP[x - 1][6]) + (S[0][x] ^ 1) + (S[1][x] ^ 0) + (S[2][x] ^ 0)
						elif itr == 5:
							DP[x][itr] = min(DP[x - 1][0], DP[x - 1][7]) + (S[0][x] ^ 1) + (S[1][x] ^ 0) + (S[2][x] ^ 1)
						elif itr == 6:
							DP[x][itr] = min(DP[x - 1][4], DP[x - 1][3]) + (S[0][x] ^ 1) + (S[1][x] ^ 1) + (S[2][x] ^ 0)
						elif itr == 7:
							DP[x][itr] = min(DP[x - 1][5], DP[x - 1][2]) + (S[0][x] ^ 1) + (S[1][x] ^ 1) + (S[2][x] ^ 1)
		ans = min(DP[-1])
		print(ans)
main()


def hasOddCnt2x2(mat, i, j):
	cnt = 0
	for ii in range(i, i + 2):
		for jj in range(j, j + 2):
			cnt += mat[ii][jj]
	return cnt % 2 == 1

def convertRowToBitMask(row):
	b = 0
	for (i, x) in enumerate(row):
		if x == 1:
			b = b | 1 << i
	return b

def nMovesToChangeB1ToB2(b1, b2):
	nMoves = 0
	for i in range(3):
		if (b1 & 1 << i > 0) != (b2 & 1 << i > 0):
			nMoves += 1
	return nMoves
b1Tob2 = [[0 for _ in range(2 ** 3)] for __ in range(2 ** 3)]
for b1 in range(8):
	for b2 in range(8):
		b1Tob2[b1][b2] = nMovesToChangeB1ToB2(b1, b2)

def main():
	(n, m) = readIntArr()
	mat = [[0 for _ in range(n)] for __ in range(m)]
	for col in range(n):
		s = input()
		for (row, x) in enumerate(s):
			mat[row][col] = int(x)
	(n, m) = (m, n)
	if n >= 4 and m >= 4:
		print(-1)
	else:
		if n == 1 or m == 1:
			print(0)
			return
		validMatches = [[] for _ in range(2 ** m)]
		doubleRows = [[0 for _ in range(m)] for __ in range(2)]
		for b1 in range(2 ** m):
			for i in range(m):
				if b1 & 1 << i > 0:
					doubleRows[0][i] = 1
				else:
					doubleRows[0][i] = 0
			for b2 in range(b1, 2 ** m):
				for i in range(m):
					if b2 & 1 << i > 0:
						doubleRows[1][i] = 1
					else:
						doubleRows[1][i] = 0
				ok = True
				for jj in range(m - 1):
					if hasOddCnt2x2(doubleRows, 0, jj) == False:
						ok = False
				if ok:
					validMatches[b1].append(b2)
					validMatches[b2].append(b1)
		dp = [[float('inf') for _ in range(2 ** m)] for __ in range(n)]
		for row in range(n):
			rowB = convertRowToBitMask(mat[row])
			for mask in range(2 ** m):
				changeMoves = b1Tob2[rowB][mask]
				if row - 1 >= 0:
					for prevMask in validMatches[mask]:
						dp[row][mask] = min(dp[row][mask], changeMoves + dp[row - 1][prevMask])
				else:
					dp[row][mask] = min(dp[row][mask], changeMoves)
		ans = float('inf')
		for mask in range(2 ** m):
			ans = min(ans, dp[n - 1][mask])
		print(ans)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

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

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

def readIntArr():
	return [int(x) for x in input().split()]

def readIntArr2():
	return [int(x) for x in input()]
main()


(n, m) = map(int, input().split())
data = [list((int(v) for v in input())) for _ in range(n)]
if n > 3 and m > 3:
	print(-1)
elif n == 1 or m == 1:
	print(0)
else:
	if n < m:
		(n, m) = (m, n)
		data = [list(t) for t in zip(*data)]
	if m == 2:
		(x, y) = (0, 0)
		for (i, v) in enumerate(data):
			if i & 1 == sum(v) & 1:
				x += 1
			else:
				y += 1
		print(min(x, y))
	elif m == 3:
		(x, y, z, w) = (0, 0, 0, 0)
		for (i, v) in enumerate(data):
			if i & 1 == sum(v[:2]) & 1 or i & 1 == sum(v[1:]) & 1:
				x += 1
			if i & 1 != sum(v[:2]) & 1 or i & 1 == sum(v[1:]) & 1:
				y += 1
			if i & 1 == sum(v[:2]) & 1 or i & 1 != sum(v[1:]) & 1:
				z += 1
			if i & 1 != sum(v[:2]) & 1 or i & 1 != sum(v[1:]) & 1:
				w += 1
		print(min(x, y, z, w))


(n, m) = list(map(int, input().split()))
g = []
for _ in range(n):
	g.append(input())
if n < m:
	new_g = [[0 for _ in range(m)] for _ in range(n)]
	for i in range(n):
		for j in range(m):
			new_g[i][j] = int(g[i][j])
else:
	new_g = [[0 for _ in range(n)] for _ in range(m)]
	for i in range(n):
		for j in range(m):
			new_g[j][i] = int(g[i][j])
	(n, m) = (m, n)
g = new_g

def get_one_count(num):
	ans = 0
	while num > 0:
		ans += num % 2
		num //= 2
	return ans

def solve(n, m, g):
	if n >= 4:
		return -1
	if n == 1:
		return 0
	if n == 2:
		prev_mask = {0: [1, 2], 1: [0, 3], 2: [0, 3], 3: [1, 2]}
		k = 4
	else:
		prev_mask = {0: [2, 5], 1: [3, 4], 2: [0, 7], 3: [1, 6], 4: [1, 6], 5: [0, 7], 6: [3, 4], 7: [2, 5]}
		k = 8
	dp = [[0 for _ in range(k)] for _ in range(m)]
	for i in range(0, m):
		cur_state = g[0][i] + g[1][i] * 2
		if n == 3:
			cur_state += g[2][i] * 4
		for kk in range(k):
			prev_states = prev_mask[kk]
			change_num = get_one_count(kk ^ cur_state)
			if i == 0:
				dp[i][kk] = change_num
				continue
			dp[i][kk] = min([dp[i - 1][prev_state] for prev_state in prev_states]) + change_num
	return min(dp[m - 1])
print(solve(n, m, g))


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
matrix = [0] * n
for i in range(n):
	line = input()
	matrix[i] = [0] * m
	for j in range(m):
		matrix[i][j] = int(line[j])
if n > m:
	matrix2 = [0] * m
	for i in range(m):
		matrix2[i] = [0] * n
		for j in range(n):
			matrix2[i][j] = matrix[i][j]
	(n, m) = (m, n)
	matrix = [0] * n
	for i in range(n):
		matrix[i] = [0] * m
		for j in range(m):
			matrix[i][j] = matrix2[i][j]
if n > 3:
	print(-1)
elif n == 1:
	print(0)
elif n == 2:
	poss = [[0, 0], [1, 0], [1, 1], [0, 1]]
	costs = [0] * 4
	for i in range(m):
		newcosts = [0] * 4
		for p in range(4):
			bc = 0
			for foo in range(2):
				if poss[p][foo] != matrix[foo][i]:
					bc += 1
			newcosts[p] = min(costs[p - 1], costs[(p + 1) % 4])
			newcosts[p] += bc
		for p in range(4):
			costs[p] = newcosts[p]
	print(min(costs))
else:
	poss1 = [[0, 0, 0], [0, 1, 0], [1, 1, 1], [1, 0, 1]]
	poss2 = [[1, 0, 0], [1, 1, 0], [0, 1, 1], [0, 0, 1]]
	costs1 = [0] * 4
	costs2 = [0] * 4
	for i in range(m):
		newcosts1 = [0] * 4
		newcosts2 = [0] * 4
		for p in range(4):
			bc1 = 0
			bc2 = 0
			for foo in range(3):
				if poss1[p][foo] != matrix[foo][i]:
					bc1 += 1
				if poss2[p][foo] != matrix[foo][i]:
					bc2 += 1
			newcosts1[p] = min(costs1[p - 1], costs1[(p + 1) % 4])
			newcosts1[p] += bc1
			newcosts2[p] = min(costs2[p - 1], costs2[(p + 1) % 4])
			newcosts2[p] += bc2
		for p in range(4):
			costs1[p] = newcosts1[p]
			costs2[p] = newcosts2[p]
	print(min(min(costs1), min(costs2)))


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
a = [list(input().rstrip()) for i in range(n)]
for i in range(n):
	for j in range(m):
		a[i][j] = int(a[i][j])
if n >= 4:
	print(-1)
	exit()
if n == 1:
	print(0)
	exit()
if n == 2:
	a.append(a[0])
r = n * m
for tar in range(4):
	tot = 0
	for (a0, a1, a2) in zip(*a):
		if a0 ^ a1 != tar & 1 or a1 ^ a2 != tar >> 1:
			tot += 1
		tar ^= 3
	if r > tot:
		r = tot
print(r)