#include <bits/stdc++.h>
using namespace std;
template <typename Arg, typename... Args>
inline void input(Arg& arg, Args&... args) {
  cin >> arg;
  (void)(int[]){0, (void(cin >> args), 0)...};
}
template <typename Arg, typename... Args>
inline void printErr(Arg&& arg, Args&&... args) {
  cerr << arg;
  (void)(int[]){0, (void(cerr << " "
                              << "\033[1;41m"
                              << ","
                              << "\033[0m"
                              << " " << args),
                    0)...};
  cerr << '\n';
};
template <class T, class... U>
void dbg(const char* sdbg, T h, U... a) {
  cerr << "\033[1;31m"
       << "Debug: "
       << "\033[0m";
  cerr << sdbg;
  cerr << " "
       << "\033[1;41m"
       << "="
       << "\033[0m"
       << " ";
  printErr(h, a...);
}
template <class S, class T>
ostream& operator<<(ostream& os, const pair<S, T>& p) {
  return os << "pair(" << p.first << "\033[1;31m"
            << ", "
            << "\033[0m" << p.second << ")";
}
template <class T>
ostream& operator<<(ostream& os, const vector<T>& p) {
  os << "\033[1;32m"
     << "vector[ "
     << "\033[0m";
  for (auto& it : p)
    os << it << "\033[1;31m"
       << ", "
       << "\033[0m";
  return os << "\033[1;32m"
            << "]"
            << "\033[0m";
}
template <class T>
ostream& operator<<(ostream& os, const set<T>& p) {
  os << "\033[1;32m"
     << "set[ ";
  for (auto& it : p)
    os << it << "\033[1;31m"
       << ", "
       << "\033[0m";
  return os << "\033[1;32m"
            << "]"
            << "\033[0m";
}
template <class S, class T>
ostream& operator<<(ostream& os, const map<S, T>& p) {
  os << "\033[1;32m"
     << "map[ "
     << "\033[0m";
  for (auto& it : p)
    os << it << "\033[1;31m"
       << ", "
       << "\033[0m";
  return os << "\033[1;32m"
            << "]"
            << "\033[0m";
}
template <class T>
void dbgIter(const char* sdbg, T a, T b) {
  cerr << "\033[1;31m"
       << "Debug: "
       << "\033[0m";
  cerr << sdbg;
  cerr << "\033[1;31m"
       << " = "
       << "\033[0m";
  cerr << "[";
  for (T i = a; i != b; ++i) {
    if (i != a) cerr << ", ";
    cerr << *i;
  }
  cerr << "]\n";
}
template <typename T>
using min_heap = priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T, typename S>
inline bool contains(map<T, S> map1, S value1) {
  return map1.find(value1) != map1.end();
}
template <typename T, typename S>
inline bool contains(T container1, S value1) {
  return container1.find(value1) != container1.end();
}
void update_image_for_k(vector<string>& arr, const int32_t k, int32_t row,
                        int32_t col) {
  if (col % k != 0) {
    col = col + k - (col % k);
    if (col - arr[0].size() > 0)
      for (string& i : arr) i.append(col - i.size(), '0');
  }
  if (row % k == 0) return;
  row = row + k - (row % k);
  if (row < arr.size()) return;
  string zeros(col, '0');
  while (arr.size() != row) {
    arr.push_back(zeros);
  }
}
void make_dp(vector<vector<int32_t>>& dp_sum, const vector<string>& arr) {
  int32_t rows = dp_sum.size(), cols = dp_sum[0].size();
  int32_t row_end = rows - 1, col_end = cols - 1;
  dp_sum[row_end][col_end] = 0;
  for (int64_t(i) = (col_end); (i) >= (0); --(i)) dp_sum[row_end][i] = 0;
  for (int64_t(i) = (row_end); (i) >= (0); --(i)) dp_sum[i][col_end] = 0;
  for (int64_t(i) = (row_end - 1); (i) >= (0); --(i)) {
    for (int64_t(j) = (col_end - 1); (j) >= (0); --(j)) {
      dp_sum[i][j] = dp_sum[i + 1][j] + dp_sum[i][j + 1] -
                     dp_sum[i + 1][j + 1] + (arr[i][j] == '1');
    }
  }
}
int32_t count_block_toggles(vector<vector<int32_t>>& dp_sum, const int32_t k,
                            int32_t x, int32_t y) {
  int32_t row_limit = dp_sum.size() - 1, col_limit = dp_sum[0].size() - 1;
  int32_t count[2] = {0, 0};
  count[1] = dp_sum[x][y] - dp_sum[min(x + k, row_limit)][y] -
             dp_sum[x][min(y + k, col_limit)] +
             dp_sum[min(x + k, row_limit)][min(y + k, col_limit)];
  count[0] = k * k - count[1];
  return min(count[0], count[1]);
}
int32_t count_toggles(vector<vector<int32_t>>& dp_sum, const int32_t k,
                      int32_t rows, int32_t cols) {
  if (rows % k != 0) rows = rows + k - (rows % k);
  if (cols % k != 0) cols = cols + k - (cols % k);
  int32_t block_rows = rows / k, block_cols = cols / k;
  int32_t count = 0;
  for (int64_t(i) = (0); (i) < (block_rows); ++(i)) {
    for (int64_t(j) = (0); (j) < (block_cols); ++(j)) {
      count += count_block_toggles(dp_sum, k, i * k, j * k);
    }
  }
  return count;
}
void solve() {
  int32_t n, m;
  cin >> n >> m;
  vector<string> arr(n);
  for (int64_t(i) = (0); (i) < (n); ++(i)) cin >> arr[i];
  int32_t n_m_max = max(n, m);
  vector<vector<int32_t>> dp_sum(arr.size() + 1,
                                 vector<int32_t>(arr[0].size() + 1));
  make_dp(dp_sum, arr);
  int32_t r = 1 << 28;
  for (int64_t(k) = (2); (k) <= (n_m_max); ++(k))
    r = min(r, count_toggles(dp_sum, k, n, m));
  cout << r << '\n';
}
int32_t main() {
  std::ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  cout.precision(20);
  cout << fixed;
  solve();
  return 0;
}
