#include <bits/stdc++.h>
using namespace std;
using i32 = std::int_fast32_t;
using i64 = std::int_fast64_t;
template <typename T>
constexpr T INF = numeric_limits<T>::has_infinity
                      ? numeric_limits<T>::infinity()
                      : numeric_limits<T>::max() / 2;
template <typename T>
istream& operator>>(istream& in, vector<T>& a) {
  for (T& x : a) cin >> x;
}
void LOG(const int& x) { cerr << x << "\n"; }
void LOG(const vector<int>& a) {
  for (int x : a) cerr << x << " ";
  cerr << "\n";
}
int ceil(int a, int b) { return (a - 1) / b + 1; }
i64 gcd(i64 a, i64 b) {
  while (b != 0) {
    i64 t = b;
    b = a % b;
    a = t;
  }
  return a;
}
i64 lcm(i64 a, i64 b) { return a / gcd(a, b) * b; }
i64 gcd(const vector<i64>& v) {
  return accumulate((v).begin(), (v).end(), 1LL,
                    static_cast<i64 (*)(i64, i64)>(gcd));
}
i64 lcm(const vector<i64>& v) {
  return v.empty() ? 0LL
                   : accumulate(v.begin() + 1, v.end(), v[0],
                                static_cast<i64 (*)(i64, i64)>(lcm));
}
class UnionFind {
 private:
  vector<int> par;
  vector<int> rnk;
  int find(int x) { return par[x] == x ? x : par[x] = find(par[x]); }

 public:
  UnionFind(int size) {
    par.resize(size);
    rnk.resize(size);
    for (int i = 0, i_len = size; i < i_len; ++i) par[i] = i, rnk[i] = 0;
  }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rnk[x] < rnk[y]) {
      par[x] = y;
    } else {
      par[y] = x;
      if (rnk[x] == rnk[y]) rnk[x]++;
    }
  }
  bool same(int x, int y) { return find(x) == find(y); }
};
struct InitCpp {
  InitCpp() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
  }
} initCpp;
signed main() {
  int n;
  cin >> n;
  set<int> r;
  int f = 0;
  for (int _ = 0, __len = n; _ < __len; ++_) {
    int a;
    cin >> a;
    if (a >= 3200) {
      f += 1;
    } else {
      r.insert(a / 400);
    }
  }
  int s = r.size();
  cout << (s) << " " << (s + f) << endl;
}
