#include <bits/stdc++.h>
#define int long long
using namespace std;

const int maxn = 2e2+8, inf  = 1e18+9, mod  = 998244353;

int n, k, a[maxn][maxn], fac[maxn], fa[maxn], sz[maxn];

int find(int u) { return u == fa[u] ? u : fa[u] = find(fa[u]); }
void solve() {
    int i, j, x, y, ans = 1;
    cin >> n >> k;
    for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) cin >> a[i][j];
    for (fac[1] = 1, i = 2; i <= n; i++) fac[i] = (fac[i - 1] * i) % mod;
    for (i = 1; i <= n; i++) fa[i] = i, sz[i] = 1;
    for (i = 1; i <= n; i++) for (j = i + 1; j <= n; j++) {
        int ok = 1;
        for (x = 1; x <= n; x++) if (a[i][x] + a[j][x] > k) { ok = 0; break; }
        if (ok) {
            int fi = find(i), fj = find(j);
            if (fi != fj) { fa[fi] = fa[fj]; sz[fj] += sz[fi]; }
        }
    }
    for (i = 1; i <= n; i++) if (fa[i] == i) ans = (ans * fac[sz[i]]) % mod;
    for (i = 1; i <= n; i++) fa[i] = i, sz[i] = 1;
    for (i = 1; i <= n; i++) for (j = i + 1; j <= n; j++) {
        int ok = 1;
        for (x = 1; x <= n; x++) if (a[x][i] + a[x][j] > k) { ok = 0; break; }
        if (ok) {
            int fi = find(i), fj = find(j);
            if (fi != fj) { fa[fi] = fa[fj]; sz[fj] += sz[fi]; }
        }
    }
    for (i = 1; i <= n; i++) if (fa[i] == i) ans = (ans * fac[sz[i]]) % mod;
    cout << ans << endl;
}

signed main() {
    ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0); //cout << fixed << setprecision(15);
    int t = 1; //cin >> t;
    while (t--) solve();
    return 0;
}
#include <bits/stdc++.h>
using namespace std;

const long long MOD=998244353;
int N, K;

long long modmypower(long long a, long long b){
  if(b==1){
    return a;
  }else if(b%2==0){
    long long c=modmypower(a,b/2);
    return (c*c)%MOD;
  }else{
    long long c=modmypower(a,(b-1)/2);
    return (((c*c)%MOD)*a)%MOD;
  }
}   

long long modfactorial(long long x){
  if(x<=1) x=1;
  else for(int i=x-1; i>0; i--) x=((x*i)%MOD);
  return x;
}

long long modinv(long long x){
  return modmypower(x,MOD-2);
}

long long fn(vector<vector<int>>& mat){
  // 交換できる行のグラフをつくる
  vector<vector<int>> g(N, vector<int>());
  for(int i=0; i<N-1; i++){
    for(int j=i+1; j<N; j++){
      bool c=true;
      for(int k=0; k<N; k++) if(mat[i][k]+mat[j][k]>K) c=false;
      if(c){
        g[i].push_back(j);
        g[j].push_back(i);
      }
    }
  }
  
  long long result=1;
  
  //連結成分ごとに見る
  vector<int> visited(N, 0);
  for(int i=0; i<N; i++){
    //連結成分を抽出
    if(visited[i]==1) continue;
    visited[i]=1;
    
    queue<int> q;
    q.emplace(i);
    
    vector<int> group;
    group.push_back(i);
    
    while(!q.empty()){
      int a=q.front();
      q.pop();
      for(auto dest:g[a]){
        if(visited[dest]==1) continue;
        visited[dest]=1;
        q.emplace(dest);
        group.push_back(dest);
      }
    }
    
    //ベクトルが一致するかどうか
    int s=group.size();
    vector<int> d(s, 0);
    for(int j=0; j<s; j++){
      for(int k=0; k<s; k++){
        if(mat[j]==mat[k]) d[j]++;
      }
    }
    
    map<int, int> dlist;
    for(int j=0; j<s; j++) dlist[d[j]]++;
    
    long long tmp=modfactorial(s);
    for(auto kv: dlist){
      int k=kv.first;
      int v=kv.second/k;
      if(k==1) continue;
      tmp=(tmp*modinv(modfactorial(v)))%MOD;
    }
    
    result=(result*tmp)%MOD;
  }
  
  return result;
}

int main(){
  cin >> N >> K;
  vector<vector<int>> A(N, vector<int>(N));
  for(int i=0; i<N*N; i++) cin >> A[i/N][i%N];
  
  long long result=fn(A);
  
  vector<vector<int>> B(N, vector<int>(N));
  for(int i=0; i<N*N; i++) B[i/N][i%N]=A[i%N][i/N];
  result*=fn(B);
  
  cout << result%MOD << endl;
}