#include <bits/stdc++.h>
using namespace std;
template <class T>
inline bool Up(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
inline bool Down(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
inline int getus() {
  int tmp, c;
  while (tmp = fgetc(stdin), tmp < '0' || tmp > '9')
    ;
  tmp -= '0';
  while (c = fgetc(stdin), '0' <= c && c <= '9') tmp = tmp * 10 + c - '0';
  return tmp;
}
inline int getint() {
  int tmp, c, flag;
  while (flag = fgetc(stdin), flag != '-' && (flag < '0' || flag > '9'))
    ;
  if (flag == '-')
    tmp = 0;
  else
    tmp = flag - '0';
  while (c = fgetc(stdin), '0' <= c && c <= '9') tmp = tmp * 10 + c - '0';
  return flag == '-' ? -tmp : tmp;
}
int N, tot;
bool mp[2048][2048], vis[2048][2048];
double dist[2048 * 2048];
vector<int> Rs, Cs;
void DFS(int x, int y) {
  if (vis[x][y]) return;
  vis[x][y] = true;
  ++tot;
  bool atBorder = false;
  for (int dx = (-1); dx <= (1); ++dx)
    for (int dy = (-1); dy <= (1); ++dy) {
      int nx = x + dx, ny = y + dy;
      if (!(1 <= nx && nx <= N)) continue;
      if (!(1 <= ny && ny <= N)) continue;
      if (!mp[nx][ny])
        atBorder = true;
      else
        DFS(nx, ny);
    }
  if (atBorder) {
    Rs.push_back(x);
    Cs.push_back(y);
  }
}
double Center(const vector<int> &a) {
  return (*max_element(a.begin(), a.end()) + *min_element(a.begin(), a.end())) *
         0.5;
}
void Work() {
  int Scnt = 0, Ccnt = 0;
  memset(vis, 0, sizeof(vis));
  for (int i = (1); i <= (N); ++i)
    for (int j = (1); j <= (N); ++j)
      if (mp[i][j] && !vis[i][j]) {
        Rs.clear();
        Cs.clear();
        tot = 0;
        DFS(i, j);
        if (tot <= 30) continue;
        int all = Rs.size();
        double centerX = Center(Rs);
        double centerY = Center(Cs);
        double avg = 0, bzc = 0, std_dist;
        for (int i = (0); i < (all); ++i)
          dist[i] = hypot(Rs[i] - centerX, Cs[i] - centerY);
        std_dist = *max_element(dist, dist + all);
        for (int i = (0); i < (all); ++i) dist[i] /= std_dist;
        avg = accumulate(dist, dist + all, 0.0) / all;
        for (int i = (0); i < (all); ++i)
          bzc += (dist[i] - avg) * (dist[i] - avg);
        bzc /= all;
        bzc = sqrt(bzc);
        if (bzc < 0.06)
          ++Ccnt;
        else
          ++Scnt;
      }
  printf("%d %d\n", Ccnt, Scnt);
}
void Init() {
  static bool tmp[2048][2048];
  memset(mp, 0, sizeof(mp));
  N = getus();
  for (int i = (1); i <= (N); ++i)
    for (int j = (1); j <= (N); ++j) tmp[i][j] = bool(getus());
  for (int i = (4); i <= (N - 3); ++i)
    for (int j = (4); j <= (N - 3); ++j)
      if (!mp[i][j]) {
        int cnt = 0;
        for (int dx = (-3); dx <= (3); ++dx)
          for (int dy = (-3); dy <= (3); ++dy) cnt += tmp[i + dx][j + dy];
        if (cnt >= 24) {
          mp[i][j] = true;
        }
      }
}
int main() {
  Init();
  Work();
  return 0;
}
