#include <bits/stdc++.h>
using namespace std;
const int N = 18;
const int R = 400;
bool Knows[N][N];
long long Dp[1 << N][N], Paths[N + 1][1 << N];
long long F[1 << N], D[1 << N], FP[R], RP[R], Res[1 << N];
int Bits[1 << N];
map<vector<int>, int> PN;
int n;
void partition(int mask, vector<int> &p) {
  p.clear();
  int cnt = 1;
  for (int i = 0; i < n - 1; i++) {
    if (mask & (1 << i))
      cnt++;
    else {
      p.push_back(cnt);
      cnt = 1;
    }
  }
  p.push_back(cnt);
  sort(p.begin(), p.end());
}
int partno(int mask) {
  vector<int> p;
  partition(mask, p);
  return PN[p];
}
long long incExl(int mask, long long *T) {
  long long ret = 0;
  for (int m = mask; m >= 0; m = (m - 1) & mask) {
    if (Bits[m ^ mask] & 1) {
      ret -= T[m];
    } else
      ret += T[m];
    if (m == 0) break;
  }
  return ret;
}
int main() {
  for (int i = 0; i < (1 << N); i++) Bits[i] = __builtin_popcount(i);
  cin >> n;
  for (int i = 0; i < n; i++) {
    string s;
    cin >> s;
    for (int j = 0; j < n; j++) Knows[i][j] = (s[j] == '1');
  }
  int pn = 0;
  for (int i = 0; i < (1 << (n - 1)); i++) {
    vector<int> p;
    partition(i, p);
    if (PN.count(p) == 0) PN[p] = pn++;
  }
  for (int i = 0; i < n; i++) Dp[(1 << i)][i] = 1;
  for (int m = 1; m < (1 << n); m++)
    for (int i = 0; i < n; i++)
      if (m & (1 << i))
        for (int j = 0; j < n; j++)
          if ((m & (1 << j)) == 0 and Knows[i][j]) {
            Dp[m | (1 << j)][j] += Dp[m][i];
          }
  for (int m = 1; m < (1 << n); m++)
    for (int i = 0; i < n; i++) Paths[Bits[m]][m] += Dp[m][i];
  ;
  for (int len = 1; len < n + 1; len++) {
    ;
    for (int m = 0; m < (1 << n); m++)
      ;
    ;
  }
  for (int len = 1; len < n + 1; len++) {
    for (int i = 0; i < n; i++)
      for (int m = (1 << n) - 1; m >= 0; m--)
        if (m & (1 << i)) {
          Paths[len][m] += Paths[len][m ^ (1 << i)];
        }
  };
  for (int len = 1; len < n + 1; len++) {
    ;
    for (int m = 0; m < (1 << n); m++)
      ;
    ;
  }
  for (int i = 0; i < pn; i++) FP[i] = RP[i] = -1;
  for (int m = 0; m < (1 << (n - 1)); m++) {
    vector<int> part;
    partition(m, part);
    int p = PN[part];
    ;
    for (int len : part)
      ;
    ;
    if (FP[p] == -1) {
      for (int i = 0; i < (1 << n); i++) D[i] = 1LL;
      for (int i = 0; i < (1 << n); i++)
        for (int len : part) {
          D[i] *= Paths[len][i];
        }
      FP[p] = incExl((1 << n) - 1, D);
    }
    F[m] = FP[p];
  };
  for (int m = 0; m < (1 << (n - 1)); m++)
    ;
  ;
  for (int i = 0; i < (1 << (n - 2)); i++)
    swap(F[i], F[i ^ ((1 << (n - 1)) - 1)]);
  for (int m = 0; m < (1 << (n - 1)); m++) Res[m] = incExl(m, F);
  for (int i = 0; i < (1 << (n - 2)); i++)
    swap(Res[i], Res[i ^ ((1 << (n - 1)) - 1)]);
  for (int m = 0; m < (1 << (n - 1)); m++) cout << Res[m] << " ";
  cout << "\n";
}
