#include <bits/stdc++.h>
using namespace std;
template <class T>
inline int __builtin_popcount(T n) {
  return (n == 0) ? 0 : (1 + __builtin_popcount(n & (n - 1)));
}
struct Ans {
  int x, y;
  bool operator<(const Ans& a) const {
    if (x * y == a.x * a.y) {
      return x < a.x;
    }
    return x * y < a.x * a.y;
  }
  Ans(int xx, int yy) {
    x = xx;
    y = yy;
  }
};
bool isOk(vector<vector<string> > vvs) {
  int N = vvs.size();
  for (int i = 0; i < (int)(N); i++) {
    vector<string> vs = vvs[i];
    int H = vs.size();
    int W = vs[0].size();
    vector<string> s0(H, ""), s1(H, ""), s2(W, ""), s3(W, "");
    for (int h = 0; h < (int)(H); h++) {
      string t0 = "", t1 = "";
      for (int w = 0; w < (int)(W); w++) {
        t0 += vs[h][w];
        t1 += vs[H - 1 - h][W - 1 - w];
      }
      s0[h] = t0;
      s1[h] = t1;
    }
    for (int w = 0; w < (int)(W); w++) {
      string t2 = "", t3 = "";
      for (int h = 0; h < (int)(H); h++) {
        t2 += vs[H - 1 - h][w];
        t3 += vs[h][W - 1 - w];
      }
      s2[w] = t2;
      s3[w] = t3;
    }
    for (int j = 0; j < (int)(N); j++) {
      if (i == j) continue;
      vector<string> vj = vvs[j];
      if (H == vj.size() && W == vj[0].size()) {
        bool isSame = true;
        for (int h = 0; h < (int)(H); h++)
          for (int w = 0; w < (int)(W); w++) {
            if (vj[h][w] != s0[h][w]) {
              isSame = false;
              h = H;
              break;
            }
          }
        if (isSame) return false;
        isSame = true;
        for (int h = 0; h < (int)(H); h++)
          for (int w = 0; w < (int)(W); w++) {
            if (vj[h][w] != s1[h][w]) {
              isSame = false;
              h = H;
              break;
            }
          }
        if (isSame) return false;
      }
      if (H == vj[0].size() && W == vj.size()) {
        bool isSame = true;
        for (int h = 0; h < (int)(H); h++)
          for (int w = 0; w < (int)(W); w++) {
            if (vj[w][h] != s2[w][h]) {
              isSame = false;
              h = H;
              break;
            }
          }
        if (isSame) return false;
        isSame = true;
        for (int h = 0; h < (int)(H); h++)
          for (int w = 0; w < (int)(W); w++) {
            if (vj[w][h] != s3[w][h]) {
              isSame = false;
              h = H;
              break;
            }
          }
        if (isSame) return false;
      }
    }
  }
  return true;
}
int main() {
  int A, B;
  cin >> A >> B;
  int primes[] = {2, 3, 5, 7, 11, 13, 17, 19};
  vector<int> divA, divB;
  {
    int tmp = A;
    while (1) {
      divA.push_back(tmp);
      divA.push_back(A / tmp);
      bool isEnd = true;
      for (int j = 0; j < (int)(7); j++) {
        if (tmp % primes[j] == 0) {
          isEnd = false;
          tmp /= primes[j];
          break;
        }
      }
      if (isEnd) break;
    }
    tmp = B;
    while (1) {
      divB.push_back(tmp);
      divB.push_back(B / tmp);
      bool isEnd = true;
      for (int j = 0; j < (int)(7); j++) {
        if (tmp % primes[j] == 0) {
          isEnd = false;
          tmp /= primes[j];
          break;
        }
      }
      if (isEnd) break;
    }
  }
  sort((divA).begin(), (divA).end());
  divA.erase(unique((divA).begin(), (divA).end()), divA.end());
  reverse((divA).begin(), (divA).end());
  sort((divB).begin(), (divB).end());
  divB.erase(unique((divB).begin(), (divB).end()), divB.end());
  reverse((divB).begin(), (divB).end());
  int resNum = 0;
  Ans res = Ans(100, 100);
  vector<string> pic(A, "");
  for (int i = 0; i < (int)(A); i++) cin >> pic[i];
  for (int i = 0; i < (int)(divA.size()); i++) {
    int a = divA[i];
    for (int j = 0; j < (int)(divB.size()); j++) {
      int b = divB[j];
      bool isGood = true;
      vector<vector<string> > tmp;
      tmp.clear();
      for (int y = 0; y < A; y += a) {
        for (int x = 0; x < B; x += b) {
          vector<string> piece;
          for (int yy = y; yy < y + a; yy++) {
            piece.push_back(pic[yy].substr(x, b));
          }
          tmp.push_back(piece);
        }
      }
      if (isOk(tmp)) {
        resNum++;
        res = min(res, Ans(a, b));
      }
    }
  }
  cout << resNum << endl;
  cout << res.x << " " << res.y << endl;
  return 0;
}
