#include <bits/stdc++.h>
using namespace std;
int A[2010][2010];
int sum[2010][2010];
bool vis[2010][2010];
int dr[] = {-1, 0, 1, 0};
int dc[] = {0, -1, 0, 1};
int query(int i, int j, int a, int b) {
  if (i > a) swap(i, a);
  if (j > b) swap(j, b);
  return sum[a][b] - (j ? sum[a][j - 1] : 0) - (i ? sum[i - 1][b] : 0) +
         ((i && j) ? sum[i - 1][j - 1] : 0);
}
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
int dfs(int i, int j) {
  if (i < 0 || j < 0 || !A[i][j] || vis[i][j]) return 0;
  vis[i][j] = true;
  int ans = 1;
  for (int mv = 0; mv < (4); ++mv) ans += dfs(i + dr[mv], j + dc[mv]);
  return ans;
}
bool works(int si, int sj, int k, int N, int M) {
  if (k <= 1) return false;
  int num_odds = 0;
  int num_ones = 0;
  for (int i = 0; i < (N); ++i)
    for (int j = 0; j < (M); ++j) {
      if (!A[i][j]) continue;
      num_ones++;
      if ((abs(i - si) % k) && (abs(j - sj) % k)) return false;
      if ((abs(i - si) % k) || (abs(j - sj) % k)) continue;
      int degree = 0;
      for (int mv = 0; mv < (4); ++mv) {
        int i2 = i + dr[mv];
        int j2 = j + dc[mv];
        if (i2 >= 0 && j2 >= 0 && i2 < N && j2 < M && A[i2][j2]) {
          degree++;
          if (query(i, j, i + dr[mv] * k, j + dc[mv] * k) != k + 1)
            return false;
        }
      }
      num_odds += (degree & 1);
    }
  if (num_odds != 0 && num_odds != 2) return false;
  memset(vis, 0, sizeof(vis));
  if (dfs(si, sj) != num_ones) return false;
  return true;
}
int main() {
  int N, M;
  cin >> N >> M;
  vector<int> ans;
  for (int i = 0; i < (N); ++i)
    for (int j = 0; j < (M); ++j) scanf("%d", &A[i][j]);
  for (int i = 0; i < (2010); ++i)
    for (int j = 0; j < (2010); ++j)
      sum[i][j] = (i ? sum[i - 1][j] : 0) + (j ? sum[i][j - 1] : 0) -
                  ((i && j) ? sum[i - 1][j - 1] : 0) + A[i][j];
  for (int si = 0; si < (N); ++si)
    for (int sj = 0; sj < (M); ++sj) {
      if (A[si][sj]) {
        int bot = 0, right = 0;
        for (int k = (si); k <= (N - 1); ++k) {
          if (!A[k][sj]) break;
          bot++;
        }
        for (int k = (sj); k <= (M - 1); ++k) {
          if (!A[si][k]) break;
          right++;
        }
        assert(bot >= 1 && right >= 1);
        int K = gcd(bot - 1, right - 1);
        vector<int> ans;
        for (int k = 1; k * k <= K; ++k) {
          if (K % k) continue;
          if (works(si, sj, k, N, M)) ans.push_back(k);
          if ((K / k != k) && works(si, sj, K / k, N, M)) ans.push_back(K / k);
        }
        if (ans.size() == 0) {
          cout << -1 << endl;
        } else {
          sort(ans.begin(), ans.end());
          for (int i = 0; i < ((int)ans.size()); ++i) {
            if (i) cout << " ";
            cout << ans[i];
          }
          cout << endl;
        }
        return 0;
      }
    }
}
