#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0);
const double EPS = 1e-9;
const int INF = 2123123123;
const int MOD = 1e9 + 7;
inline void OPEN(const string &s) {
  freopen((s + ".in").c_str(), "r", stdin);
  freopen((s + ".out").c_str(), "w", stdout);
}
int n, m;
int a[1000 + 5][1000 + 5], vis[1000 + 5][1000 + 5], id[1000 + 5][1000 + 5];
vector<pair<int, int> > node;
vector<pair<int, int> > edges[1000 * 1000 + 5];
int in(pair<int, int> p) {
  int r = p.first, c = p.second;
  return !(r < 1 || r > n || c < 1 || c > m);
}
void dfs(int v) {
  if (vis[node[v].first][node[v].second]) return;
  vis[node[v].first][node[v].second] = 1;
  for (int i = 0; i < (int)(edges[v]).size(); i++) dfs(edges[v][i].first);
}
int gcd(int a, int b) {
  if (!b) return a;
  return gcd(b, a % b);
}
int main() {
  scanf("%d %d", &n, &m);
  int f = 1;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) scanf("%d", &a[i][j]);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      if (!a[i][j]) continue;
      int r = 0, c = 0;
      if (a[i - 1][j] || a[i + 1][j]) r = 1;
      if (a[i][j - 1] || a[i][j + 1]) c = 1;
      if ((r && c) ||
          (a[i - 1][j] + a[i + 1][j] + a[i][j - 1] + a[i][j + 1] < 2)) {
        node.push_back(make_pair(i, j));
        id[i][j] = (int)(node).size();
      }
    }
  for (int i = 0; i < (int)(node).size(); i++) {
    int c;
    pair<int, int> p;
    p = node[i];
    ++p.second;
    c = 1;
    while (in(p) && !id[p.first][p.second] && a[p.first][p.second]) {
      ++p.second;
      ++c;
    }
    if (id[p.first][p.second])
      edges[i].push_back(make_pair(id[p.first][p.second] - 1, c));
    p = node[i];
    --p.second;
    c = 1;
    while (in(p) && !id[p.first][p.second] && a[p.first][p.second]) {
      --p.second;
      ++c;
    }
    if (id[p.first][p.second])
      edges[i].push_back(make_pair(id[p.first][p.second] - 1, c));
    p = node[i];
    --p.first;
    c = 1;
    while (in(p) && !id[p.first][p.second] && a[p.first][p.second]) {
      --p.first;
      ++c;
    }
    if (id[p.first][p.second])
      edges[i].push_back(make_pair(id[p.first][p.second] - 1, c));
    p = node[i];
    ++p.first;
    c = 1;
    while (in(p) && !id[p.first][p.second] && a[p.first][p.second]) {
      ++p.first;
      ++c;
    }
    if (id[p.first][p.second])
      edges[i].push_back(make_pair(id[p.first][p.second] - 1, c));
  }
  int odd = 0;
  for (int i = 0; i < (int)(node).size(); i++) {
    if ((int)(edges[i]).size() % 2) ++odd;
  }
  if (odd > 2) f = 0;
  dfs(0);
  for (int i = 0; i < (int)(node).size(); i++) {
    if (!vis[node[i].first][node[i].second]) f = 0;
  }
  int ans = 0;
  for (int i = 0; i < (int)(node).size(); i++) {
    for (int j = 0; j < (int)(edges[i]).size(); j++)
      ans = gcd(ans, edges[i][j].second);
  }
  if (ans < 2) f = 0;
  if (!f)
    puts("-1");
  else {
    for (int i = 2; i <= ans; i++)
      if (!(ans % i)) printf("%d ", i);
  }
  puts("");
  return 0;
}
