package yukicoder; import java.util.*; public class Q460 { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int M = sc.nextInt(); int N = sc.nextInt(); int[][] a = new int[M][N]; for (int i = 0; i < M; ++i) { for (int j = 0; j < N; ++j) { a[i][j] = sc.nextInt(); } } int[][] mx = new int[M * N][M * N]; int[] v = new int[M * N]; for (int i = 0; i < M; ++i) { for (int j = 0; j < N; ++j) { v[i * N + j] = a[i][j]; } } for (int i = 0; i < M; ++i) { for (int j = 0; j < N; ++j) { for (int dx = -1; dx <= 1; ++dx) { for (int dy = -1; dy <= 1; ++dy) { int nx = j + dx; int ny = i + dy; if (nx < 0 || ny < 0 || nx >= N || ny >= M) continue; mx[i * N + j][ny * N + nx] = 1; } } } } for (int i = 0; i < M * N; ++i) { int j = i; while (j < M * N && mx[j][i] == 0) { ++j; } if (j == M * N) continue; if (i != j) { for (int k = 0; k < N * M; ++k) { int d = mx[i][k]; mx[i][k] = mx[j][k]; mx[j][k] = d; } int d = v[i]; v[i] = v[j]; v[j] = d; } for (int k = 0; k < M * N; ++k) { if (k == i) continue; if (mx[k][i] == 1) { for (int l = 0; l < M * N; ++l) { mx[k][l] = (mx[k][l] + mx[i][l]) % 2; } v[k] = (v[k] + v[i]) % 2; } } } ArrayList[] to = new ArrayList[N * M]; for (int i = 0; i < N * M; ++i) { to[i] = new ArrayList<>(); } int c = 0; ArrayList pending = new ArrayList<>(); for (int i = N * M - 1; i >= 0; --i) { for (int k = 0; k < N * M; ++k) { if (mx[i][k] == 1) { to[k].add(i); } } ArrayDeque tmp = new ArrayDeque<>(); for (int k = i + 1; k < N * M; ++k) { if (mx[i][k] == 1) { tmp.add(k); } } if (tmp.size() > 0) { pending.addAll(tmp); continue; } if (tmp.size() == 0 && mx[i][i] == 1 && v[i] == 1) { ++c; for (int k = 0; k <= i; ++k) { if (mx[k][i] == 1) { v[k] = v[k] ^ 1; } } } else if (v[i] == 1 && mx[i][i] == 0 && tmp.size() == 0) { if (mx[i][i] != 1) { System.out.println("Impossible"); return; } } } int ans = Integer.MAX_VALUE; Collections.sort(pending); for (int i = 0; i < pending.size(); ++i) { while (i + 1 < pending.size() && pending.get(i) == pending.get(i + 1)) { pending.remove(i + 1); } } out: for (int i = 0; i < (1 << pending.size()); ++i) { int[] nv = Arrays.copyOf(v, v.length); int used = 0; for (int k = 0; k < pending.size(); ++k) { if ((i & (1 << k)) > 0) { ++used; for (int t : to[pending.get(k)]) { nv[t] ^= 1; } } } for (int j = 0; j < N * M; ++j) { if (nv[j] == 1) { if (mx[j][j] == 0) continue out; else { ++used; nv[j] ^= 1; } } } ans = Math.min(ans, c + used); } System.out.println(ans); } static void show(int[][] mx, int[] v, int M, int N) { for (int i = 0; i < M * N; ++i) { for (int j = 0; j < M * N; ++j) { System.out.print(mx[i][j] + " "); } System.out.print(v[i]); System.out.println(); } } static void tr(Object... objects) { System.out.println(Arrays.deepToString(objects)); } }