#include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define dup(x,y) (((x)+(y)-1)/(y))
#define ALL(x) (x).begin(), (x).end()
typedef long long ll;
typedef pair<int, int> pii;
const double EPS = 1e-10;
const int INF = 1e9;
const ll LINF = 1e18;
const int MOD = 998244353;
const double PI = acos(-1);
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};

struct dsu {
	public:
		dsu(int n): cnt(n), par(n), siz(n, 1) {
			for (int i = 0; i < n; i++) par[i] = i;
		}
		bool merge(int x, int y) {
			x = find(x);
			y = find(y);
			if (x == y) return false;
			if (siz[x] < siz[y]) swap(x, y);
			siz[x] += siz[y];
			par[y] = x;
			--cnt;
			return true;
		}
		int find(int x) {
			return par[x] == x ? x : par[x] = find(par[x]);
		}
		int size(int x) {
			return siz[find(x)];
		}
		bool same(int x, int y) {
			return find(x) == find(y);
		}
		int groups() {
			return cnt;
		}
	private:
		int cnt;
		vector<int> par, siz;
};

int main() {
	int n, d;
	cin >> n >> d;
	vector<vector<int>> a(n, vector<int>(n));
	rep(i,n) rep(j,n) cin >> a[i][j];
	dsu h(n), w(n);
	ll ans = 1;
	rep(i,n) {
		rep(k,n) {
			bool b = true;
			rep(j,n) {
				if (a[i][j] + a[k][j] > d) b = false;
			}
			if (b) h.merge(i, k);
		}
	}
	map<int, int> mph;
	rep(i,n) {
		if (mph[h.find(i)]) continue;
		int m = h.size(i);
		for (int j = 1; j <= m; j++) {
			ans *= j;
			ans %= MOD;
		}
		mph[h.find(i)]++;
	}

	rep(j,n) {
		rep(k,n) {
			bool b = true;
			rep(i,n) {
				if (a[i][j] + a[i][k] > d) b = false;
			}
			if (b) w.merge(j, k);
		}
	}
	map<int, int> mpw;
	rep(i,n) {
		if (mpw[w.find(i)]) continue;
		int m = w.size(i);
		for (int j = 1; j <= m; j++) {
			ans *= j;
			ans %= MOD;
		}
		mpw[w.find(i)]++;
	}
	cout << ans << endl;
}
#include <bits/stdc++.h> 
using namespace std;
using ll = long long;
template<typename T> using v2 = vector<vector<T>>;
template<typename T> inline v2<T> fill(int r, int c, const T& t){ return v2<T>(r, vector<T>(c, t)); }
#define F first
#define S second

const int MOD = 998244353;
inline int add(int a, int b){ return (a+b)%MOD; }
inline int sub(int a, int b){ return ((a-b)%MOD + MOD)%MOD; }
inline int mul(int a, int b){ return ((ll)a*b)%MOD; }

int n, k;
v2<int> adjc, adjr;
vector<int> v, fact;

int dfs(v2<int>& adj, int node){
    v[node] = true;
    int ans = 1;
    for(int i : adj[node]){
        if(!v[i])
            ans += dfs(adj, i);
    }
    return ans;
}

int ways(v2<int>& adj){
    int x = 1;
    v = vector<int>(n, false);
    for(int i = 0; i < n; ++i){
        if(!v[i]){
            int s = dfs(adj, i);
            x = mul(x, fact[s]);
        }
    }
    return x;
}

void solve(){
    cin >> n >> k;

    v2<int> m = fill(n,n,-1);
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < n; ++j){
            cin >> m[i][j];
        }
    }

    adjc = v2<int>(n), adjr = v2<int>(n);
    for(int x = 0; x < n; ++x){
        for(int y = x+1; y < n; ++y){
            bool okc=true, okr=true;
            for(int i = 0; i < n; ++i){
                if(m[i][x]+m[i][y] > k){
                    okc = false;
                }
                if(m[x][i]+m[y][i] > k){
                    okr = false;
                }
            }
            if(okc){
                adjc[x].push_back(y);
                adjc[y].push_back(x);
            }
            if(okr){
                adjr[x].push_back(y);
                adjr[y].push_back(x);
            }
        }
    }

    fact = vector<int>(n+1);
    fact[0] = 1;
    for(int i = 1; i <= n; ++i){
        fact[i] = mul(i, fact[i-1]);
    }

    int r = ways(adjr);
    int c = ways(adjc);
    int ans = mul(r, c);
    cout << ans << "\n";
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
    return 0;
}