#include <bits/stdc++.h>
const int maxN = 2000;
const unsigned int mod = 998244353;
constexpr int inf = INT_MAX;
class Array {
 public:
  inline const int *begin() const { return data; }
  inline const int *end() const { return endPtr; }
  inline void push_back(const int x) { *(endPtr++) = x; }
  inline size_t size() const { return endPtr - data; }
  template <class T>
  inline void foreach (T fun) const {
    std::for_each<const int *>(data, endPtr, fun);
  }

 private:
  int data[maxN + 10], *endPtr = data;
};
Array edgeIn[maxN + 10], edgeOut[maxN + 10];
int originDegree[maxN + 10], degree[maxN + 10];
inline void reset(const int n) {
  std::memcpy(degree, originDegree, sizeof(degree[0]) * n);
}
void readGraph(const int n) {
  for (int i = 0; i < n; ++i) {
    static char str[maxN + 10];
    std::cin >> str;
    for (int j = 0; j < n; ++j)
      if (str[j] == '1') {
        edgeIn[j].push_back(i);
        edgeOut[i].push_back(j);
        ++originDegree[i];
      }
  }
}
bool isStrongConnect(const int n) {
  std::sort(degree, degree + n);
  int sum = 0;
  for (int i = 0; i + 1 < n; ++i) {
    sum += degree[i];
    if (i * (i + 1) / 2 == sum) return false;
  }
  return true;
}
void reverseSet(const int n, const unsigned int set) {
  for (int i = 0; i < n; ++i)
    for (auto to : edgeOut[i])
      if ((((set) >> (i)) & 0x01u) ^ (((set) >> (to)) & 0x01u)) {
        --degree[i];
        ++degree[to];
      }
}
inline bool checkSet(const int n, const unsigned int set) {
  reset(n);
  reverseSet(n, set);
  return isStrongConnect(n);
}
void reverseSingle(const int vertex) {
  edgeOut[vertex].foreach ([](int p) { ++degree[p]; });
  edgeIn[vertex].foreach ([](int p) { --degree[p]; });
  degree[vertex] = edgeIn[vertex].size();
}
inline bool checkSingle(const int n, const int vertex) {
  reset(n);
  reverseSingle(vertex);
  return isStrongConnect(n);
}
unsigned int factor(const unsigned int n) {
  unsigned int ret = 1;
  for (unsigned int i = 2; i <= n; ++i) ret = (ret * i) % mod;
  return ret;
}
std::pair<int, int> enumSet(const int n) {
  int count = inf, solution = 0;
  const unsigned int msk = 1u << n;
  for (unsigned int i = 1; i < msk; ++i) {
    const int cnt = __builtin_popcount(i);
    if (cnt <= count && checkSet(n, i)) {
      if (cnt == count)
        ++solution;
      else {
        solution = 1;
        count = cnt;
      }
    }
  }
  return std::make_pair(count,
                        count != inf ? (solution * factor(count)) % mod : 0);
}
std::pair<int, int> enumVertex(const int n) {
  int solution = 0;
  for (int i = 0; i < n; ++i) solution += checkSingle(n, i);
  return std::make_pair(1, solution);
}
int main() {
  std::ios::sync_with_stdio(false);
  int n;
  std::cin >> n;
  readGraph(n);
  reset(n);
  if (isStrongConnect(n)) {
    std::cout << "0 1\n";
    return 0;
  }
  const auto [count, solution] = n <= 6 ? enumSet(n) : enumVertex(n);
  if (count == inf)
    std::cout << "-1\n";
  else
    std::cout << count << " " << solution << "\n";
  return 0;
}
