#include <bits/stdc++.h>
using namespace std;
template <typename T, typename U>
void upmin(T& a, const U& b) {
  a = min<T>(a, b);
}
template <typename T, typename U>
void upmax(T& a, const U& b) {
  a = max<T>(a, b);
}
template <typename T>
void uniq(T& a) {
  sort(a.begin(), a.end());
  a.erase(unique(a.begin(), a.end()), a.end());
}
template <typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}
template <typename T>
void print(T a, int n, const string& split = " ") {
  for (int i = 0; i < n; i++) {
    cout << a[i];
    if (i + 1 != n) cout << split;
  }
  cout << endl;
}
template <typename T>
void print2d(T a, int w, int h, int width = -1, int br = 1) {
  for (int i = 0; i < h; ++i) {
    for (int j = 0; j < w; ++j) {
      if (width != -1) cout.width(width);
      cout << a[i][j] << ' ';
    }
    cout << endl;
  }
  while (br--) cout << endl;
}
const int dx[] = {0, 1, 0, -1};
const int dy[] = {1, 0, -1, 0};
bool in_rect(int x, int y, int w, int h) {
  return 0 <= x && x < w && 0 <= y && y < h;
}
int h, w, a[1024][1024];
int num_mark = 0;
int mx = -1, my;
int sum_row[1024][1024], sum_col[1024][1024];
bool check(int k) {
  int degree[1024][1024];
  for (int y = 0; y < (int)(h); y++)
    for (int x = 0; x < (int)(h); x++) degree[y][x] = 0;
  int mark = 0;
  for (int y = my % k; y < h; y += k) {
    for (int x = mx % k; x < w; x += k) {
      mark += a[y][x];
      int tx = x + k;
      if (tx < w && a[y][tx] && sum_row[y][tx] - sum_row[y][x] == k) {
        mark += k - 1;
        ++degree[y][x];
        ++degree[y][tx];
      }
      int ty = y + k;
      if (ty < h && a[ty][x] && sum_col[ty][x] - sum_col[y][x] == k) {
        mark += k - 1;
        ++degree[y][x];
        ++degree[ty][x];
      }
    }
  }
  if (mark < num_mark) return false;
  int odd = 0;
  for (int y = 0; y < (int)(h); y++)
    for (int x = 0; x < (int)(h); x++) {
      if (degree[y][x] & 1) {
        if (++odd > 2) return false;
      }
    }
  return true;
}
bool connected() {
  static bool mark[1024][1024];
  for (int y = 0; y < (int)(h); y++)
    for (int x = 0; x < (int)(w); x++) mark[y][x] = a[y][x];
  queue<pair<int, int> > q;
  q.push(pair<int, int>(mx, my));
  while (!q.empty()) {
    int x = q.front().first, y = q.front().second;
    q.pop();
    for (int dir = 0; dir < (int)(4); dir++) {
      int nx = x + dx[dir], ny = y + dy[dir];
      if (in_rect(nx, ny, w, h) && mark[ny][nx]) {
        mark[ny][nx] = false;
        q.push(pair<int, int>(nx, ny));
      }
    }
  }
  for (int y = 0; y < (int)(h); y++)
    for (int x = 0; x < (int)(w); x++)
      if (mark[y][x]) return false;
  return true;
}
int main() {
  cin >> h >> w;
  for (int y = 0; y < (int)(h); y++)
    for (int x = 0; x < (int)(w); x++) {
      cin >> a[y][x];
      num_mark += a[y][x];
      if (mx == -1 && a[y][x]) mx = x, my = y;
    }
  if (!connected()) {
    cout << -1 << endl;
    return 0;
  }
  for (int y = 0; y < (int)(h); y++)
    for (int x = 0; x < (int)(w); x++)
      sum_row[y][x + 1] = sum_row[y][x] + a[y][x];
  for (int x = 0; x < (int)(w); x++)
    for (int y = 0; y < (int)(h); y++)
      sum_col[y + 1][x] = sum_col[y][x] + a[y][x];
  vector<int> res;
  for (int k = 2; k <= 1000; k++)
    if (check(k)) res.push_back(k);
  if (res.empty())
    cout << -1 << endl;
  else {
    for (auto i : res) cout << i << endl;
  }
}
