#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
typedef long double ld;
typedef double db; 
typedef string str;
 
typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
 
typedef vector<int> vi; 
typedef vector<bool> vb; 
typedef vector<ll> vl; 
typedef vector<db> vd; 
typedef vector<str> vs; 
typedef vector<pi> vpi;
 
#define sz(x) (int)(x).size()
#define f first
#define s second
#define all(x) x.begin(), x.end()
#define sor(x) sort(all(x))
#define ins insert 
#define ft front() 
#define bk back()
#define pf push_front 
#define pb push_back
#define endl '\n'
 
const ll MOD = 998244353;
const int MX = 2e5 + 5;
const ll INF = 1e18;
const ld PI = acos((ld)-1);
const int xd[4] = {1, 0, -1, 0}, yd[4] = {0, 1, 0, -1};

void setIO() {
   ios_base::sync_with_stdio(0);
   cin.tie(0); cout.tie(0);
}

int main() {
   setIO();
   int n, k;
   cin >> n >> k;
   vector<vi> a(n, vi(n));
   for (vi &i : a) {
      for (int &j : i)
         cin >> j;
   }
   vector<vi> g_c(n), g_r(n);
   for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
         bool e = true;
         for (int l = 0; l < n; l++)
            if (a[l][i] + a[l][j] > k) e = false;
         if (e) {
            g_c[i].pb(j);
            g_c[j].pb(i);
         }
         e = true;
         for (int l = 0; l < n; l++)
            if (a[i][l] + a[j][l] > k) e = false;
         if (e) {
            g_r[i].pb(j);
            g_r[j].pb(i);
         }
      }
   }
   vi cmp_c(n, -1), cmp_r(n, -1);
   int cur = 0;
   queue<int> q;
   int n_cmp_c = 0;
   while (true) {
      while (cur < n && cmp_c[cur] >= 0)
         cur++;
      if (cur == n) break;
      q.push(cur);
      cmp_c[cur] = n_cmp_c;
      while (!q.empty()) {
         int v = q.ft;
         q.pop();
         for (int to : g_c[v]) {
            if (cmp_c[to] == -1) {
               cmp_c[to] = n_cmp_c;
               q.push(to);
            }
         }
      }
      n_cmp_c++;
   }
   cur = 0;
   int n_cmp_r = 0;
   while (true) {
      while (cur < n && cmp_r[cur] >= 0)
         cur++;
      if (cur == n) break;
      q.push(cur);
      cmp_r[cur] = n_cmp_r;
      while (!q.empty()) {
         int v = q.ft;
         q.pop();
         for (int to : g_r[v]) {
            if (cmp_r[to] == -1) {
               cmp_r[to] = n_cmp_r;
               q.push(to);
            }
         }
      }
      n_cmp_r++;
   }
   vl cnt_c(n_cmp_c), cnt_r(n_cmp_r);
   for (int i = 0; i < n; i++) {
      cnt_c[cmp_c[i]]++;
      cnt_r[cmp_r[i]]++;
   }
   ll ans = 1;
   for (ll i : cnt_c) {
      for (int j = 2; j <= i; j++)
         ans = ans * j % MOD;
   }
   for (ll i : cnt_r) {
      for (int j = 2; j <= i; j++)
         ans = ans * j % MOD;
   }
   cout << ans << endl;
   return 0;
}
#include<bits/stdc++.h>

#define DONTSYNC ios_base::sync_with_stdio(false);   cin.tie(NULL); cout.tie(NULL) //dont use stdio with iostream functions //input and output are out of order now!
#define TEST unsigned long long T; cin>>T; while(T--)  //loop over each testcase
#define endl "\n"
#define fori(a,start,end) for(int a=start;a<end;a++)
#define forll(a,start,end) for(long long a=start;a<end;a++)
#define forull(a,start,end) for(unsigned long long a=start;a<end;a++)
#define MOD 998244353
typedef long long ll;
typedef unsigned long long ull;

using namespace std;

int N,K;
int getroot(int a,vector<int> &par){
    if(par[a]==a) return a;
    return par[a]=getroot(par[a],par);
}
void joinsets(int a,int b,vector<int> &par,vector<int> &siz){
    int roota=getroot(a,par),rootb=getroot(b,par);
    if(roota!=rootb){
        par[rootb]=roota;
        siz[roota]+=siz[rootb];
    }
}
bool check(int isrow,int a,int b,vector< vector<int> > &mat){
    if(isrow){
        fori(col,0,N){
            if(mat[a][col]+mat[b][col]>K) return false;
        }
    }
    else{
        fori(row,0,N){
            if(mat[row][a]+mat[row][b]>K) return false;
        }
    }
    return true;
}
void solve(){
    /* code */
     cin>>N>>K;
    long long res=1;
    vector<int> fact(N+1); fact[0]=1; fori(i,1,N+1) fact[i]=(1ll*fact[i-1]*i)%MOD;
    vector< vector<int> > mat(N,vector<int>(N));
    fori(i,0,N) fori(j,0,N) cin>>mat[i][j];
    ////////
    vector<int> par(N);
    vector<int> siz(N);
    fori(i,0,N) par[i]=i,siz[i]=1;
    fori(a,0,N-1){
        fori(b,a+1,N){
            if (check(1,a,b,mat)) joinsets(a,b,par,siz);
        }
    }
    // vector<int> count(N,1);
    fori(i,0,N) if(getroot(i,par)==i) res=(res*fact[siz[i]])%MOD;
    //////
    fori(i,0,N) par[i]=i,siz[i]=1;
    fori(a,0,N-1){
        fori(b,a+1,N){
            if (check(0,a,b,mat)) joinsets(a,b,par,siz);
        }
    }
    // fill(count.begin(),count.end(),1);
    fori(i,0,N) if(getroot(i,par)==i) res=(res*fact[siz[i]])%MOD;

    cout<<res;
}

int main()
{
    DONTSYNC;
    // TEST{
        solve();
    // }
    return 0;
}
