#include <bits/stdc++.h>
using namespace std;
const int maxn = 8005;
vector<vector<bool> > adj(maxn, vector<bool>(maxn));
bool before(int a, int b) {
  if (adj[a][b])
    return true;
  else
    return false;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int n;
  cin >> n;
  vector<int> outdegree(n);
  string s;
  int cnode = -1, minout = n;
  for (int i = 0; i < n; i++) {
    cin >> s;
    outdegree[i] = 0;
    for (int j = 0; j < n / 4; j++) {
      int num = ((int)s[j] >= 65) ? (int)s[j] - 55 : (int)s[j] - 48;
      for (int k = 3; k >= 0; k--) {
        adj[i][4 * j + k] = (num % 2 == 0) ? 0 : 1;
        outdegree[i] += num % 2;
        num /= 2;
      }
    }
    if (outdegree[i] < minout) minout = outdegree[i], cnode = i;
  }
  vector<int> a, b;
  for (int i = 0; i < n; i++)
    if (i != cnode) {
      if (adj[i][cnode])
        a.push_back(i);
      else {
        b.push_back(i);
        assert(adj[cnode][i]);
      }
    }
  sort(a.begin(), a.end(), before);
  sort(b.begin(), b.end(), before);
  reverse(b.begin(), b.end());
  int x = a.size(), y = b.size();
  long long int total = 0;
  total += (x * (x - 1)) / 2 + (y * (y - 1)) / 2;
  int direct_edges = 0;
  for (int i = 0; i < x; i++) direct_edges += outdegree[a[i]];
  direct_edges = direct_edges - (x * (x + 1)) / 2;
  total += (2 * (x * y - direct_edges) + direct_edges);
  if (y > 0) {
    stack<int> reachable_idxs;
    int lastb = b[0];
    vector<vector<int> > a_sets, b_sets;
    vector<int> aset, bset;
    int z = 0;
    for (int i = 0; i < x; i++) {
      if (adj[lastb][a[i]])
        reachable_idxs.push(i);
      else {
        if (reachable_idxs.empty())
          z++;
        else
          aset.push_back(i);
      }
    }
    a_sets.push_back(aset);
    aset.resize(0);
    for (int i = 0; i < b.size(); i++) {
      if (adj[b[i]][a[reachable_idxs.top()]])
        bset.push_back(i);
      else {
        b_sets.push_back(bset);
        while (!adj[b[i]][a[reachable_idxs.top()]]) {
          aset.push_back(reachable_idxs.top());
          reachable_idxs.pop();
        }
        a_sets.push_back(aset);
        bset.resize(0), aset.resize(0);
        bset.push_back(i);
      }
    }
    b_sets.push_back(bset);
    while (!reachable_idxs.empty()) {
      aset.push_back(reachable_idxs.top());
      reachable_idxs.pop();
    }
    a_sets.push_back(aset);
    total += 2 * ((x - z) * (x - z - 1)) / 2;
    for (int i = 0; i < a_sets.size(); i++) {
      int sz = a_sets[i].size();
      total += (sz * (sz - 1)) / 2;
    }
    total += ((long long int)(614 * n)) * (x - z) * z;
    total += ((long long int)(614 * n)) * (z * (z - 1)) / 2;
    total += 2 * (y * (y - 1)) / 2;
    for (int i = 0; i < b_sets.size(); i++) {
      int sz = b_sets[i].size();
      total += (sz * (sz - 1)) / 2;
    }
    total += y * (x - z);
    int not_reach = 0;
    for (int i = 0; i < a_sets.size() - 1; i++)
      not_reach += (int)a_sets[i].size();
    for (int i = b_sets.size() - 1; i >= 0; i--) {
      int bsize = b_sets[i].size(), asize = a_sets[i].size();
      total += bsize * not_reach;
      not_reach -= asize;
    }
    total += ((long long int)(614 * n)) * y * z;
    total += 2 * y;
    total += 2 * (x - z) + (int)a_sets[0].size();
    total += ((long long int)(614 * n)) * z;
  } else
    total += ((long long int)(614 * n)) * (x * (x + 1)) / 2;
  total += (x + y);
  cout << total << endl;
  return 0;
}
