#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2000;
const int INF = 0x3f3f3f3f;
template <class T>
void Read(T &x) {
  x = 0;
  char c = getchar();
  bool flag = 0;
  while (c < '0' || '9' < c) {
    if (c == '-') flag = 1;
    c = getchar();
  }
  while ('0' <= c && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  if (flag) x = -x;
}
double G[MAXN + 10][MAXN + 10];
double tmp[MAXN + 10][MAXN + 10];
int n;
const int dx[8] = {0, -1, 0, 1, 1, -1, 1, -1};
const int dy[8] = {-1, 0, 1, 0, -1, -1, 1, 1};
const double lim = 0.4;
void Pre_Work() {
  memcpy(tmp, G, sizeof(G));
  int x, y, t;
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) {
      t = 1;
      for (int k = 0; k < 8; ++k) {
        x = i + dx[k], y = j + dy[k];
        if (x < 1 || y < 1 || x > n || y > n) continue;
        ++t;
        G[i][j] += tmp[x][y];
      }
      G[i][j] /= t;
    }
}
bool mp[MAXN + 10][MAXN + 10];
bool vis[MAXN + 10][MAXN + 10];
bool used[MAXN + 10][MAXN + 10];
int ans1, ans2;
queue<pair<int, int> > que;
void check(int tx, int ty) {
  double ctx = 0, cty = 0;
  que.push(make_pair(tx, ty));
  vis[tx][ty] = true;
  int cnt = 0;
  pair<int, int> now, newed;
  while (!que.empty()) {
    now = que.front(), que.pop();
    ctx += now.first, cty += now.second;
    ++cnt;
    for (int i = 0; i < 4; ++i) {
      newed.first = now.first + dx[i];
      newed.second = now.second + dy[i];
      if (newed.first < 1 || newed.second < 1 || newed.first > n ||
          newed.second > n)
        continue;
      if (mp[newed.first][newed.second] && !vis[newed.first][newed.second]) {
        vis[newed.first][newed.second] = true;
        que.push(newed);
      }
    }
  }
  ctx /= cnt, cty /= cnt;
  que.push(make_pair(tx, ty));
  used[tx][ty] = true;
  double mx = 0, mn = INF, t;
  while (!que.empty()) {
    now = que.front(), que.pop();
    int tt = 0;
    for (int i = 0; i < 4; ++i) {
      newed.first = now.first + dx[i];
      newed.second = now.second + dy[i];
      if (newed.first < 1 || newed.second < 1 || newed.first > n ||
          newed.second > n)
        continue;
      if (!mp[newed.first][newed.second]) continue;
      ++tt;
      if (!used[newed.first][newed.second]) {
        used[newed.first][newed.second] = true;
        que.push(newed);
      }
    }
    if (tt < 4) {
      t = sqrt((now.first - ctx) * (now.first - ctx) +
               (now.second - cty) * (now.second - cty));
      mx = fmax(mx, t), mn = fmin(mn, t);
    }
  }
  if (mn < 8) return;
  if (mx / mn <= 1.2)
    ++ans1;
  else
    ++ans2;
}
int main() {
  Read(n);
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) Read(G[i][j]);
  for (int i = 1; i <= 5; ++i) Pre_Work();
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j) mp[i][j] = (G[i][j] >= lim);
  ans1 = ans2 = 0;
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j)
      if (mp[i][j] && !vis[i][j]) check(i, j);
  printf("%d %d\n", ans1, ans2);
}
