#include <bits/stdc++.h>
using namespace std;
int N, M, table[1005][1005];
vector<int> line;
int yy, xx;
int dp[1005][1005];
int degree[1005][1005], sumdegree, node;
int pass[1005][1005], gcd_val;
int query(int y1, int x1, int y2, int x2) {
  return dp[y2][x2] - dp[y1 - 1][x2] - dp[y2][x1 - 1] + dp[y1 - 1][x1 - 1];
}
int gcd(int a, int b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}
void rec(int y, int x, int k) {
  node++;
  pass[y][x] = true;
  if (y - k >= 1 && query(y - k, x, y, x) == k + 1) {
    degree[y - k][x]++;
    sumdegree++;
    if (!pass[y - k][x]) rec(y - k, x, k);
  }
  if (y + k <= N && query(y, x, y + k, x) == k + 1) {
    degree[y + k][x]++;
    sumdegree++;
    if (!pass[y + k][x]) rec(y + k, x, k);
  }
  if (x + k <= M && query(y, x, y, x + k) == k + 1) {
    degree[y][x + k]++;
    sumdegree++;
    if (!pass[y][x + k]) rec(y, x + k, k);
  }
  if (x - k >= 1 && query(y, x - k, y, x) == k + 1) {
    degree[y][x - k]++;
    sumdegree++;
    if (!pass[y][x - k]) rec(y, x - k, k);
  }
}
bool test(int k) {
  for (int i = 1; i <= N; i++)
    for (int j = 1; j <= M; j++) degree[i][j] = pass[i][j] = 0;
  sumdegree = 0;
  node = 0;
  rec(yy, xx, k);
  int count[2];
  count[0] = count[1] = 0;
  for (int i = 1; i <= N; i++)
    for (int j = 1; j <= M; j++) count[degree[i][j] % 2]++;
  if (count[1] == 2) {
    sumdegree = (sumdegree) / 2 * (k - 1) + node;
  } else if (count[1] == 0) {
    sumdegree = sumdegree / 2 * (k - 1) + node;
  }
  return (count[1] == 0 || count[1] == 2) && (sumdegree == dp[N][M]);
}
int main() {
  scanf("%d %d", &N, &M);
  for (int i = 1; i <= N; i++)
    for (int j = 1; j <= M; j++) scanf("%d", &table[i][j]);
  for (int i = 1; i <= N; i++)
    for (int j = 1; j <= M; j++) {
      dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + table[i][j];
    }
  for (int i = 1; i <= N; i++) {
    int cc, idx = 1;
    while (idx <= M) {
      cc = 0;
      while (idx <= M && table[i][idx] == 0) idx++;
      while (idx <= M && table[i][idx] == 1) cc++, idx++;
      if (cc > 1) line.push_back(cc - 1);
    }
  }
  for (int i = 1; i <= M; i++) {
    int cc, idx = 1;
    while (idx <= N) {
      cc = 0;
      while (idx <= N && table[idx][i] == 0) idx++;
      while (idx <= N && table[idx][i] == 1) cc++, idx++;
      if (cc > 1) line.push_back(cc - 1);
    }
  }
  if (!line.empty()) {
    gcd_val = line[0];
    int ss = line.size();
    for (int i = 1; i < ss; i++) gcd_val = gcd(gcd_val, line[i]);
  } else {
    gcd_val = 1;
  }
  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= M; j++) {
      if (table[i][j] == 1) {
        yy = i, xx = j;
        break;
      }
    }
    if (yy) break;
  }
  if (gcd_val == 1) {
    printf("-1\n");
    return 0;
  }
  bool space = false;
  int minval = min(N, M);
  for (int k = 2; k <= minval; k++) {
    if (k % gcd_val > 0 && gcd_val % k > 0) continue;
    if (test(k)) {
      if (space) printf(" ");
      space = true;
      printf("%d", k);
    }
  }
  if (!space) printf("-1");
  printf("\n");
  return 0;
}
