#include<bits/stdc++.h>

using namespace std;

#define FOR(i, x, y) for(int i = (x); i < (y); ++i)
#define REP(i, x, y) for(int i = (x); i <= (y); ++i)
#define PB push_back
#define MP make_pair
#define PH push
#define fst first
#define snd second
typedef long long ll;
typedef unsigned long long ull;
typedef double lf;
typedef long double Lf;
typedef pair<int, int> pii;

const int maxn = 55;
const int INF = 998244353;

int n, k, ans = 1;
int fac[maxn];
int a[maxn][maxn];

class Dsu{
private:
public:
	int fa[maxn], sz[maxn];
	inline void init(){ FOR(i, 0, n) fa[i] = i, sz[i] = 1; return; }
	inline int find(int x){ return (fa[x] == x) ? x : (fa[x] = find(fa[x])); }
	inline void merge(int x, int y){
		x = find(x), y = find(y);
		if(x == y)
			return;
		sz[y] += sz[x];
		fa[x] = y;
		return;
	}
}row, col;

int main(){
	scanf("%d%d", &n, &k);
	FOR(i, 0, n) FOR(j, 0, n)
		scanf("%d", &a[i][j]);
	
	row.init();
	col.init();
	fac[0] = 1;
	REP(i, 1, n)
		fac[i] = 1ll * fac[i - 1] * i % INF;
	FOR(x, 0, n) FOR(y, 0, n){
		bool frow = true, fcol = true;
		FOR(i, 0, n){
			fcol &= (a[i][x] + a[i][y] <= k);
			frow &= (a[x][i] + a[y][i] <= k);
		}
		if(frow)
			row.merge(x, y);
		if(fcol)
			col.merge(x, y);
	}

	FOR(i, 0, n){
		if(row.find(i) == i)
			ans = 1ll * fac[row.sz[i]] * ans % INF;
		if(col.find(i) == i)
			ans = 1ll * fac[col.sz[i]] * ans % INF;
	}
		
	printf("%d\n", ans);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
typedef long long i64;
const int MOD = 998244353;
const int inv2 = 499122177;
const int N = 52;
int c[N * N][N * N] = {0};
int p[N * N][N * N] = {0};
int f[N * N] = {1};

void init() {
    for (int i = 1, fac = 1; i < N * N; i++) {
        f[i] = 1LL * f[i - 1] * i % MOD;
        c[i][0] = c[i][i] = 1;
        for (int j = 1; j < i; j++) {
            c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
            p[i][j] = 1LL * c[i][j] * f[i] % MOD;
        }
    }
}

bool check_row(int x, int y, int k, const vector<vector<int>>& a) {
    for (int i = 0; i < a.size(); i++) {
        if (a[x][i] + a[y][i] > k) {
            return false;
        }
    }
    return true;
}

bool check_col(int x, int y, int k, const vector<vector<int>>& a) {
    for (int i = 0; i < a.size(); i++) {
        if (a[i][x] + a[i][y] > k) {
            return false;
        }
    }
    return true;
}

int set_find(int x, vector<int>& f) { return f[x] = (f[x] == x) ? x : set_find(f[x], f); }

void set_union(int x, int y, vector<int>& f) {
    x = f[x], y = f[y];
    if (x > y) {
        swap(x, y);
    }
    f[y] = x;
}

int main() {
    init();

    int n, k;
    cin >> n >> k;
    vector<vector<int>> a(n, vector<int>(n, 0));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cin >> a[i][j];
        }
    }

    vector<int> row_root(n, 1);
    vector<int> row_set_count(n, 0);
    vector<int> col_root(n, 1);
    vector<int> col_set_count(n, 0);

    for (int i = 0; i < n; i++) {
        row_root[i] = i;
        col_root[i] = i;
    }

    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (check_row(i, j, k, a)) {
                set_union(i, j, row_root);
            }
            if (check_col(i, j, k, a)) {
                set_union(i, j, col_root);
            }
        }
    }

    for (int i = 0; i < n; i++) {
        row_set_count[set_find(row_root[i], row_root)]++;
        col_set_count[set_find(col_root[i], col_root)]++;
    }

    int ans_row = 1, ans_col = 1;
    for (int i = 0; i < n; i++) {
        ans_row *= f[row_set_count[i]];
        ans_row %= MOD;
        ans_col *= f[col_set_count[i]];
        ans_col %= MOD;
    }

    printf("%lld\n", 1LL * ans_row * ans_col % MOD);
    return 0;
}
/*
10 150
82 94 21 65 28 22 61 80 81 79
93 35 59 85 96 1 78 72 43 5
12 15 97 49 69 53 18 73 6 58
60 14 23 19 44 99 64 17 29 67
24 39 56 92 88 7 48 75 36 91
74 16 26 10 40 63 45 76 86 3
9 66 42 84 38 51 25 2 33 41
87 54 57 62 47 31 68 11 83 8
46 27 55 70 52 98 20 77 89 34
32 71 30 50 90 4 37 95 13 100
*/