#pragma GCC optimize("O3")
#include<bits/stdc++.h> 
using namespace std;
using ll=long long;
using P=pair<ll,ll>;
template<class T> using V=vector<T>; 
#define fi first
#define se second
#define all(v) (v).begin(),(v).end()
const ll inf=(1e18);
const ll mod=998244353;
//const ll mod=1000000007;
const vector<int> dy={-1,0,1,0},dx={0,-1,0,1};
ll GCD(ll a,ll b) {return b ? GCD(b,a%b):a;}
ll LCM(ll c,ll d){return c/GCD(c,d)*d;}
struct __INIT{__INIT(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(20);}} __init;
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T>void debag(const vector<T> &a){cerr<<"debag :";for(auto v:a)cerr<<v<<" ";cerr<<"\n";}
template<class T>void print(const vector<T> &a){for(auto v:a)cout<<v<<" ";cout<<"\n";}
struct mint{
using ull=unsigned long long int;
ull v;
mint(ll vv=0){s(vv%mod+mod);}
mint& s(ull vv){
v=vv<mod?vv:vv-mod;
return *this;
}
//オーバーロード
mint operator-()const{return mint()-*this;}//mint型にキャスト
mint&operator+=(const mint&val){return s(v+val.v);}
mint&operator-=(const mint&val){return s(v+mod-val.v);}
mint&operator*=(const mint&val){
v=ull(v)*val.v%mod;
return *this;
}
mint&operator/=(const mint&val){return *this*=val.inv();}
mint operator+(const mint&val){return mint(*this)+=val;}
mint operator-(const mint&val){return mint(*this)-=val;}
mint operator*(const mint&val){return mint(*this)*=val;}
mint operator/(const mint&val){return mint(*this)/=val;}
mint pow(ll n)const{
mint res(1),x(*this);
while(n){
if(n&1)res*=x;
x*=x;
n>>=1ll;
}
return res;
}
mint inv()const{return pow(mod-2);}
//拡張ユークリッドの互除法
/* mint inv()const{
int x,y;
int g=extgcd(v,mod,x,y);
assert(g==1);
if(x<0)x+=mod;
return mint(x);
}*/
friend ostream& operator<<(ostream&os,const mint&val){
return os<<val.v;
}//出力
bool operator<(const mint&val)const{return v<val.v;}
bool operator==(const mint&val)const{return v==val.v;}
bool operator>(const mint&val)const{return v>val.v;}
};
const ll MAX = 2000010;//設定
mint fac[MAX], finv[MAX], inv[MAX];
// テーブルを作る前処理
void init(){
fac[0] = fac[1] = 1;
for(int i=1;i<MAX;i++)fac[i]=fac[i-1]*i;
finv[MAX-1]=fac[MAX-1].inv();
for(int i=MAX-2;i>=0;i--)finv[i]=finv[i+1]*(i+1);
for(int i=MAX-2;i>=1;i--)inv[i]=finv[i]+fac[i-1];
}
//階乗
mint factor(ll n,ll k){
if (n<k) return 0;
if (n<0 || k<0) return 0;
return fac[n]*finv[k];
}
// 二項係数計算
mint COM(int n, int k){
if (n < k) return 0;
if (n < 0 || k < 0) return 0;
return fac[n] * finv[k] * finv[n - k];
}
class UF{
public:
	vector<int> par,num;
	int find(int v){
		return (par[v]==v)? v: (par[v]=find(par[v]));
	}
	explicit UF(int N):par(N),num(N,1){
		iota(all(par),0);
	}
	void unite(int u,int v){
		u=find(u),v=find(v);
		if(u==v)return;
		if(num[u]<num[v])swap(u,v);
		num[u]+=num[v];
		par[v]=u;
	}
	bool same(int u,int v){
		return find(u)==find(v);
	}
	bool ispar(int v){
		return v=find(v);
	}
	int size(int v){
		return num[find(v)];
	}
};
int main(){
    init();
    int n,K;
    cin>>n>>K;
    V<V<int>> a(n,V<int>(n));
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++)cin>>a[i][j];
    }
    UF l(n);
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            bool ok=true;
            for(int k=0;k<n;k++){
                  if(a[i][k]+a[j][k]>K)ok=false;
            }
            if(ok)l.unite(i,j);
        }
    }
    mint ans=mint(1);
    for(int i=0;i<n;i++){
         if(l.find(i)!=i)continue;
         ans*=fac[l.size(i)];
    }
    UF r(n);
        for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            bool ok=true;
            for(int k=0;k<n;k++){
                  if(a[k][i]+a[k][j]>K)ok=false;
            }
            if(ok)r.unite(i,j);
        }
    }
        for(int i=0;i<n;i++){
         if(r.find(i)!=i)continue;
         ans*=fac[r.size(i)];
    }
    cout<<ans<<"\n";
}

// Problem: C - Shuffle Permutation
// Contest: AtCoder - AtCoder Regular Contest 107
// URL: https://atcoder.jp/contests/arc107/tasks/arc107_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)

#include <bits/stdc++.h>
using namespace std;
#define ff         first
#define ss         second
#define endl       '\n'
#define pb         push_back
#define int        long long
#define vi         vector<int>
#define mii        map<int, int>
#define pii        pair<int, int>
#define all(x)     (x).begin(), (x).end()
#define fill(a,b)  memset(a, b, sizeof(a))
#define setbits(x) __builtin_popcountll(x)
#define rep(i,x,y) for(int i=(int)x; i<y; i++)
#define px(a)      for(auto x: a) cout<<x<<" "; cout<<'\n';
#define pxy(a,n)   rep(i,0,n) {px(a[i])};

const long long MOD=998244353,N=1e5+5;
int power(int x, unsigned int y)  
{  
    int res = 1;
    x = x % MOD;
    if (x == 0) return 0;
  
    while (y > 0)  
    { 
        if (y & 1)  
            res = (res*x) % MOD;
        y = y>>1;
        x = (x*x) % MOD;  
    }  
    return res;  
}
int fact[N];
void factorial(int n){
	fact[0]=1;
	for(int i=1;i<=n;i++){
		fact[i]=fact[i-1]*i;
		if(fact[i]>=MOD)
			fact[i]%=MOD;
	}
}
class dsu {
 public:
  vector<int> p;
  int n;
 
  dsu(int _n) : n(_n) {
    p.resize(n);
    iota(p.begin(), p.end(), 0);
  }
 
  inline int get(int x) {
    return (x == p[x] ? x : (p[x] = get(p[x])));
  }
 
  inline bool unite(int x, int y) {
    x = get(x);
    y = get(y);
    if (x != y) {
      p[x] = y;
      return true;
    }
    return false;
  }
};
int32_t main()
{	
	std::ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	//Remove incase of Online Query
	
	factorial(55);
	int n,kk,ans=1; cin>>n>>kk;
	int a[n][n];
	rep(i,0,n) rep(j,0,n) cin>>a[i][j];
	dsu r(n),c(n);
	rep(i,0,n) rep(j,i+1,n){
		rep(k,0,n){
			if(a[i][k]+a[j][k]>kk) goto end;
		}
		r.unite(i,j);
		end:;
	}
	rep(i,0,n) rep(j,i+1,n){
		rep(k,0,n){
			if(a[k][i]+a[k][j]>kk) goto end1;
		}
		c.unite(i,j);
		end1:;
	}
	int r_val[n]={0};
	int c_val[n]={0};
	rep(i,0,n){
		r_val[r.get(i)]++;
		c_val[c.get(i)]++;
	}
	// px(r_val);
	// px(c_val);
	rep(i,0,n){
		ans*=fact[r_val[i]];
		ans%=MOD;
		ans*=fact[c_val[i]];
		ans%=MOD;
	}
	cout<<ans<<endl;
	return 0;
}