#include <bits/stdc++.h>
using namespace std;
const int maxn = 2000 + 10;
const int dx[] = {1, -1, 0, 0, 1, -1, 1, -1};
const int dy[] = {0, 0, 1, -1, 1, -1, -1, 1};
int ma[maxn][maxn], n;
bool v[maxn][maxn];
int in(int x, int y) { return x >= 0 && x < n && y >= 0 && y < n; }
struct point {
  double x, y;
  point(double x, double y) : x(x), y(y) {}
  point() : x(0), y(0) {}
  bool operator<(const point &o) const {
    if (fabs(x - o.x) < 1E-7) return y < o.y;
    return x < o.x;
  }
};
vector<point> pts;
void dfs(int x, int y) {
  pts.push_back(point(x, y));
  v[x][y] = true;
  for (int i = 0; i < 4; ++i) {
    int nx = x + dx[i], ny = y + dy[i];
    if (in(nx, ny) && !v[nx][ny]) {
      if (ma[nx][ny]) {
        dfs(nx, ny);
      }
    }
  }
}
const double PI = acos(-1.0);
double sqr(double x) { return x * x; }
const double EPS = 1E-7;
const int rotime = 100;
const double magic = PI * .5 / rotime;
const int consize = 100000;
point sh[consize];
inline int dcmp(double x) { return x < -EPS ? -1 : x > EPS; }
double cross(const point &a, const point &b, const point &c) {
  return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
}
int check() {
  sort(pts.begin(), pts.end());
  int tot = 0;
  int n = pts.size();
  for (int i = 0; i < n; ++i) {
    while (tot >= 2 && dcmp(cross(sh[tot - 2], sh[tot - 1], pts[i])) <= 0)
      tot--;
    sh[tot++] = pts[i];
  }
  int lev = tot;
  for (int i = n - 2; i >= 0; --i) {
    while (tot > lev && dcmp(cross(sh[tot - 2], sh[tot - 1], pts[i])) <= 0)
      tot--;
    sh[tot++] = pts[i];
  }
  double area = 0;
  int sn = tot - 1;
  for (int i = 0; i < sn; ++i) {
    area += sh[i].x * sh[i + 1].y - sh[i].y * sh[i + 1].x;
  }
  area = fabs(area) * .5;
  double mind = 1E20;
  double sinA = sin(magic), cosA = cos(magic);
  for (int i = 0; i < rotime; ++i) {
    double x1 = 1E20;
    double y1 = 1E20;
    double x2 = -1E20;
    double y2 = -1E20;
    for (int j = 0; j < sn; ++j) {
      x1 = min(x1, sh[j].x);
      y1 = min(y1, sh[j].y);
      x2 = max(x2, sh[j].x);
      y2 = max(y2, sh[j].y);
    }
    mind = min(mind, (x2 - x1) * (y2 - y1));
    for (int j = 0; j < sn; ++j) {
      sh[j] = point(sh[j].x * cosA - sh[j].y * sinA,
                    sh[j].x * sinA + sh[j].y * cosA);
    }
  }
  if (mind <= 150) {
    return -2;
  }
  double pr = area / mind;
  if (pr <= 0.892699081698724) {
    return 0;
  } else {
    return 1;
  }
}
int A[maxn][maxn];
int main() {
  scanf("%d", &n);
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      scanf("%d", &ma[i][j]);
    }
  }
  vector<pair<int, int> > ans;
  int circleN = 0;
  int squareN = 0;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (ma[i][j] && !v[i][j]) {
        pts.clear();
        dfs(i, j);
        if (pts.size() <= 150) continue;
        int ty = check();
        if (ty == 1) {
          ans.push_back(make_pair(pts.size(), 1));
        } else if (ty == 0) {
          ans.push_back(make_pair(pts.size(), 0));
        }
      }
    }
  }
  sort(ans.begin(), ans.end(), greater<pair<int, int> >());
  for (int i = 0; i < 50 && i < ans.size(); ++i) {
    if (ans[i].second == 1) {
      squareN++;
    } else {
      circleN++;
    }
  }
  cout << circleN << " " << squareN << endl;
}
