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

#define M 998244353
#define int long long

vector<int> root, sze;

int find_set(int a) {
    if (a == root[a])
        return a;
    return root[a] = find_set(root[a]);
}

void unite(int a, int b) {
    int x = find_set(a);
    int y = find_set(b);
    if (x != y) {
        if (sze[y] > sze[x])
            swap(x, y);
        root[y] = x;
        sze[x] += sze[y];
    }
}

int32_t main() {
    int n, k;
    cin >> n >> k;
    root.resize(n);
    sze.resize(n, 1);
    iota(root.begin(), root.end(), 0);
    vector<vector<int>> arr(n, vector<int> (n));
    vector<int> fact(n+1, 1);
    for (int i = 2; i <= n; i++)
        fact[i] = (fact[i-1] * i) % M;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cin >> arr[i][j];
    for (int x = 0; x < n-1; x++) {
        for (int y = x+1; y < n; y++) {
            int poss = 1;
            for (int j = 0; j < n; j++) {
                if (arr[x][j] + arr[y][j] > k) {
                    poss = 0;
                    break;
                }
            }
            if (poss == 1)
                unite(x, y);
        }
    }
    int ans = 1;
    for (int i = 0; i < n; i++)
        if (root[i] == i)
            ans = (ans * fact[sze[i]]) % M;
    root.clear();
    sze.clear();
    root.resize(n);
    sze.resize(n, 1);
    iota(root.begin(), root.end(), 0);
    for (int x = 0; x < n-1; x++) {
        for (int y = x+1; y < n; y++) {
            int poss = 1;
            for (int i = 0; i < n; i++) {
                if (arr[i][x] + arr[i][y] > k) {
                    poss = 0;
                    break;
                }
            }
            if (poss == 1)
                unite(x, y);
        }
    }
    for (int i = 0; i < n; i++)
        if (root[i] == i)
            ans = (ans * fact[sze[i]]) % M;
    cout << ans << endl;
}

#include <bits/stdc++.h>
typedef long long LL;
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define RALL(X) (X).rbegin(), (X).rend()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define RI(X) scanf("%d", &(X))
#define RII(X, Y) scanf("%d%d", &(X), &(Y))
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))
#define DRI(X) int (X); scanf("%d", &X)
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)
#define DRVI(N, X) VI X(N); for (int ___I=0; ___I<n; ___I++) scanf("%d", &(X[___I]))  
#define RS(X) scanf("%s", (X))
#define CASET int ___T, case_n = 1; scanf("%d ", &___T); while (___T-- > 0)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define PII pair<int,int>
#define VI vector<int>
#define VL vector<long long>
#define VPII vector<pair<int,int> >
#define PLL pair<long long,long long>
#define VPLL vector<pair<long long,long long> >
#define F first
#define S second

using namespace std;

VI ps;

int findp(int i){
    if (ps[i]!=i){
        ps[i]=findp(ps[i]);
    } 
    return ps[i];
}

void merge(int i, int j){
    i=findp(i);
    j=findp(j);
    ps[j]=i;
}

int main(){
    DRII(n,k);
    vector<VI> a(n,VI(n,0));
    REP(i,n){
        REP(j,n){
            RI(a[i][j]);
        }
    }

    vector<VI> cs(n,VI(0));
    LL r=1;
    const int mod = 998244353;
    REP(i,n){
        REPP(j,i+1,n){
            bool cansw=true;
            REP(p,n){
                if (a[i][p]+a[j][p]>k) {cansw=false; break;}
            }
            if (cansw){
                cs[i].PB(j);
                cs[j].PB(i);
            }
        }
    }
    ps=VI(n);
    REP(i,n) ps[i]=i;
    REP(i,n){
        for (auto c:cs[i]){
            merge(i,c);
        }
    }
    map<int,int> v;
    REP(i,n){
        r*=(++v[findp(i)]);
        r%=mod;
    }


    // La même pour les cols
    cs=vector<VI>(n,VI(0));
    REP(i,n) ps[i]=i;
    v.clear();
    REP(i,n){
        REPP(j,i+1,n){
            bool cansw=true;
            REP(p,n){
                if (a[p][i]+a[p][j]>k) {cansw=false; break;}
            }
            if (cansw){
                cs[i].PB(j);
                cs[j].PB(i);
            }
        }
    }
    ps=VI(n);
    REP(i,n) ps[i]=i;
    REP(i,n){
        for (auto c:cs[i]){
            merge(i,c);
        }
    }
    REP(i,n){
        r*=(++v[findp(i)]);
        r%=mod;
    }

    printf("%lld\n",r);
}
