#include <bits/stdc++.h>
using namespace std;
using i64 = int_fast64_t;
bool adj[18][18];
i64 dp[1<<18][18];
i64 lenCnt[19][1<<18];
// length = 2^N
template <typename T> void subset_transform(int N, T a[1<<18]) {
for (int k = 1; k < (1<<N); k *= 2) {
for (int i = 0; i < (1<<N); i += 2*k) {
for (int j = 0; j < k; j++) {
a[i+j+k] += a[i+j];
}
}
}
}
template <typename T> void inverse_superset_transform(int N, T a[1<<18]) {
for (int k = 1; k < (1<<N); k *= 2) {
for (int i = 0; i < (1<<N); i += 2*k) {
for (int j = 0; j < k; j++) {
a[i+j] -= a[i+j+k];
}
}
}
}
i64 ans[1<<17];
int main() {
ios::sync_with_stdio(0), cin.tie(0);
int N; cin >> N;
for (int i = 0; i < N; i++) {
string s; cin >> s;
for (int j = 0; j < N; j++) {
adj[i][j] = s[j] - '0';
}
}
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))) continue;
for (int j = 0; j < N; j++) {
if (m & (1<<j)) continue;
if (adj[i][j]) {
dp[m | (1<<j)][j] += dp[m][i];
}
}
}
}
for (int m = 1; m < (1<<N); m++) {
int pc = __builtin_popcount(m);
for (int i = 0; i < N; i++) {
lenCnt[pc][m] += dp[m][i];
}
}
for (int l = 1; l <= N; l++) {
subset_transform(N, lenCnt[l]);
}
map<vector<int>, i64> memo;
for (int p = 0; p < (1<<(N-1)); p++) {
int cnt = 0;
vector<int> partition;
for (int i = 0; i < N; i++) {
cnt++;
if (!(p & (1<<i))) {
partition.push_back(cnt);
cnt = 0;
}
}
sort(partition.begin(), partition.end());
if (!memo.count(partition)) {
i64 res = 0;
for (int m = 1; m < (1<<N); m++) {
i64 v = 1;
for (int l : partition) {
v *= lenCnt[l][m];
}
if ((N - __builtin_popcount(m)) % 2 == 0) {
res += v;
} else {
res -= v;
}
}
memo[partition] = res;
}
ans[p] = memo[partition];
}
inverse_superset_transform(N-1, ans);
for (int p = 0; p < (1<<(N-1)); p++) { cout << ans[p] << " \n"[p==(1<<(N-1))-1]; }
return 0;
}