#include <bits/stdc++.h>   #pragma GCC optimize( -O2 )   using namespace std;   void err(istream_iterator<string> it) { cerr << endl; }   template <typename T, typename... Args>   void err(istream_iterator<string> it, T a, Args... args) {     cerr << *it <<   =   << a <<   t ;     err(++it, args...);   }   template <typename T1, typename T2>   ostream& operator<<(ostream& c, pair<T1, T2>& v) {     c <<  (  << v.first <<  ,  << v.second <<  ) ;     return c;   }   template <template <class...> class TT, class... T>   ostream& operator<<(ostream& out, TT<T...>& c) {     out <<  {  ;     for (auto& x : c) out << x <<    ;     out <<  } ;     return out;   }   const int LIM = 1.5e3 + 5, MOD = 998244353;   const long double EPS = 1e-9;   int read() {     int xx = 0, ff = 1;     char ch = getchar();     while (ch >  9  || ch <  0 ) {       if (ch ==  - ) ff = -1;       ch = getchar();     }     while (ch >=  0  && ch <=  9 ) {       xx = (xx << 3) + (xx << 1) + ch -  0 ;       ch = getchar();     }     return xx * ff;   }   mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());   int n;   int link[LIM], sz[LIM], edges[LIM];   long long poly[LIM][LIM];   int find(int x) {     if (x == link[x]) return x;     return link[x] = find(link[x]);   }   void polymul(int a, int b) {     long long temp[LIM] = {0};     for (int i = 0; i < n + 1; ++i) {       for (int j = 0; j + i <= n; j++) {         temp[i + j] += (poly[a][i] * poly[b][j]) % MOD;       }     }     for (int i = 0; i < LIM; ++i) {       poly[a][i] = temp[i] % MOD;     }     return;   }   void unite(int a, int b) {     a = find(a);     b = find(b);     if (sz[a] < sz[b]) swap(a, b);     if (a == b) {       edges[a]++;       if (edges[a] == sz[a] * (sz[a] - 1) / 2) {         poly[a][1]++;       }       return;     }     link[b] = a;     sz[a] += sz[b];     polymul(a, b);     edges[a]++;     edges[a] += edges[b];     if (edges[a] == sz[a] * (sz[a] - 1) / 2) {       poly[a][1]++;     }   }   int main() {     ios_base::sync_with_stdio(0);     cin.tie(0);     cin >> n;     for (int i = 0; i < n; ++i) {       poly[i][1] = 1;       link[i] = i;       sz[i] = 1;     }     vector<tuple<int, int, int>> v;     for (int i = 0; i < n; ++i) {       for (int j = 0; j < n; ++j) {         int x;         cin >> x;         if (i < j) {           v.push_back({x, i, j});         }       }     }     sort(v.begin(), v.end());     for (auto& r : v) {       int cost, first, second;       tie(cost, first, second) = r;       unite(first, second);     }     int a = find(0);     for (int i = 1; i < n + 1; ++i) {       cout << poly[a][i] % MOD <<    ;     }     cout <<   n ;     return 0;   }   