#include<bits/stdc++.h>
using namespace std;
//#define MOD 1000000007
#define MOD 998244353
#define INF 1000000010
#define EPS 1e-9
#define F first
#define S second

#define debug(x) cout<<x<<endl;
#define repi(i,x,n) for(int i=x;i<n;i++)
#define rep(i,n) repi(i,0,n)
#define lp(i,n) repi(i,0,n)
#define repn(i,n) for(int i=n;i>=0;i--)
#define int long long
#define endl "\n"

typedef pair<int,int> PII;
typedef pair<int,string> PIS;
typedef pair<string,int> PSI;

struct UnionFind{
  vector<int> data;

  UnionFind(int N){
    data.assign(N,-1);
  }

 bool unite(int x, int y) {
    x = find(x), y = find(y);
    if(x == y) return (false);
    if(data[x] > data[y]) swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
 
  int find(int k) {
    if(data[k] < 0) return (k);
    return (data[k] = find(data[k]));
  }
 
  int size(int k) {
    return (-data[find(k)]);
  }
};


signed main(){
  cin.tie(0);	
  ios::sync_with_stdio(false);
  int n,k;
  cin>>n>>k;
  UnionFind uf1=UnionFind(50),uf2=UnionFind(50);//1=tate,2=yoko;
  int mp[n][n];
  rep(i,n){
    rep(j,n){
      cin>>mp[i][j];
    }
  }
  rep(i,n){
    repi(j,i+1,n){
      bool flag=true;
      rep(l,n){
	if(mp[i][l]+mp[j][l]>k) flag=false;
      }
      if(flag){
	uf1.unite(i,j);
      }
    }
  }
  rep(i,n){
    repi(j,i+1,n){
      bool flag=true;
      rep(l,n){
	if(mp[l][i]+mp[l][j]>k) flag=false;
      }
      if(flag){
	uf2.unite(i,j);
      }
    }
  }
  int flag1[50]={},flag2[50]={};
  int cnt1=1,cnt2=1;
  rep(i,50){
    if(flag1[uf1.find(i)]==0){
      flag1[uf1.find(i)]++;
      for(int j=0;j<uf1.size(i);j++){
	cnt1*=(j+1);
	cnt1%=MOD;
      }
    }
     if(flag2[uf2.find(i)]==0){
      flag2[uf2.find(i)]++;
      for(int j=0;j<uf2.size(i);j++){
	cnt2*=(j+1);
	cnt2%=MOD;
      }
    }
  }
  cout<<(cnt1*cnt2)%MOD<<endl;
  return 0;
}

// Hail god Yato
 
#include <bits/stdc++.h> 
using namespace std;
 
#define hs ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
typedef long long ll;
const ll MOD = 998244353;
const ll INF = 1e18;
const ll MAX = 52;
//
//
ll frac[52];
void dfs(int idx, vector<int> &vis, vector<vector<int>> &g, int &cnt){
    if(vis[idx])
        return ;
    vis[idx] = 1;
    ++cnt;
    for(int e : g[idx])
        dfs(e, vis, g, cnt);
}
void solve(){
    int n, k;
    cin>>n>>k;
    frac[0] = 1;
    for(int i = 1; i < 52; i++)
        frac[i] = (frac[i-1]*i)%MOD;
    vector<vector<int>> vec(n, vector<int>(n));
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            cin>>vec[i][j];
    
    vector<vector<int>> g(52, vector<int>());
    for(int i = 0; i < n; i++)
        for(int j = i+1; j < n; j++){
            bool flag = true;
            for(int t = 0; t < n; t++){
                if(vec[i][t] + vec[j][t] > k){
                    flag = false;
                    break;
                }
            }
            if(flag){
                g[i].push_back(j);
                g[j].push_back(i);
            }
        }
    ll ans = 1;
    vector<int> vis(52, 0);
    for(int i = 0; i < n; i++){
        int cnt = 0;
        dfs(i, vis, g, cnt);
        ans *= frac[cnt];
        ans %= MOD;
    }

    for(int i = 0; i < 52; i++){
        g[i].clear();
        vis[i] = 0;
    }
    for(int i = 0; i < n; i++)
        for(int j = i+1; j < n; j++){
            bool flag = true;
            for(int t = 0; t < n; t++){
                if(vec[t][i] + vec[t][j] > k){
                    flag = false;
                    break;
                }
            }
            if(flag){
                g[i].push_back(j);
                g[j].push_back(i);
            }
        }
        ll ans2 = 1;
    for(int i = 0; i < n; i++){
        int cnt = 0;
        dfs(i, vis, g, cnt);
        ans2 *= frac[cnt];
        ans2 %= MOD;
    }
    ans *= ans2;
    ans %= MOD;
    cout<<ans;
}
int main(){ 
        hs;
        ll t;
        t=1;
        // cin>>t;
        for (int i=1; i<=t; i++){
                //cout<<"Case #"<<i<<": ";
                solve();
         }
        return 0; 
}