#include <bits/stdc++.h>
using namespace std;
struct part {
  vector<vector<char> > M;
  part rotate() {
    part ret;
    int i, j, n = M.size(), m = M[0].size();
    for (j = 0; j < m; ++j) {
      ret.M.push_back(vector<char>());
      for (i = n - 1; i >= 0; --i) ret.M.back().push_back(M[i][j]);
    }
    return ret;
  }
  void print() {
    for (int i = 0; i < M.size(); ++i) {
      for (int j = 0; j < M[i].size(); ++j) cout << M[i][j];
      cout << endl;
    }
  }
  bool operator<(const part& w) const {
    if (M.size() < w.M.size()) return true;
    if (M.size() > w.M.size()) return false;
    if (M[0].size() < w.M[0].size()) return true;
    if (M[0].size() > w.M[0].size()) return false;
    for (int i = 0; i < M.size(); ++i) {
      if (M[i] < w.M[i]) return true;
      if (M[i] > w.M[i]) return false;
    }
    return false;
  }
};
set<part> in;
int n, m;
char V[30][30];
bool TRY(int x, int y) {
  int i, j, k, l;
  part p1, p2, p3, p4;
  in.clear();
  p1.M.resize(x);
  for (i = 0; i < x; ++i) p1.M[i].resize(y);
  for (i = 0; i < n; i += x)
    for (j = 0; j < m; j += y) {
      for (k = 0; k < x; ++k)
        for (l = 0; l < y; ++l) p1.M[k][l] = V[i + k][j + l];
      p2 = p1.rotate();
      p3 = p2.rotate();
      p4 = p3.rotate();
      if (in.find(p1) != in.end() || in.find(p2) != in.end() ||
          in.find(p3) != in.end() || in.find(p4) != in.end())
        return false;
      in.insert(p1);
    }
  return true;
}
int main() {
  int i, j, k, l;
  cin >> n >> m;
  for (i = 0; i < n; ++i) cin >> V[i];
  int x, y, bx = n, by = m, bv = n * m;
  int br = 0;
  for (x = 1; x <= n; ++x) {
    if (n % x != 0) continue;
    for (y = 1; y <= m; ++y) {
      if (m % y != 0) continue;
      if (!TRY(x, y)) continue;
      ++br;
      if (bv > x * y) {
        bv = x * y;
        bx = x;
        by = y;
      }
    }
  }
  cout << br << '\n';
  cout << bx << ' ' << by << '\n';
  return 0;
}
