/*** author: yuji9511 ***/
#include <bits/stdc++.h>
// #include <atcoder/all>
// using namespace atcoder;
using namespace std;
using ll = long long;
using lpair = pair<ll, ll>;
const ll MOD = 998244353;
const ll INF = 1e18;
#define rep(i,m,n) for(ll i=(m);i<(n);i++)
#define rrep(i,m,n) for(ll i=(m);i>=(n);i--)
#define printa(x,n) for(ll i=0;i<n;i++){cout<<(x[i])<<" \n"[i==n-1];};
void print() {}
template <class H,class... T>
void print(H&& h, T&&... t){cout<<h<<" \n"[sizeof...(t)==0];print(forward<T>(t)...);}
#define debug(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << "\n"
struct UnionFind {
private:
    ll N;
    vector<ll> parent;
    vector<ll> num;
    vector<ll> diff_weight;

public:
    UnionFind(ll n){
        N = n;
        rep(i,0,N) parent.push_back(i);
        rep(i,0,N) num.push_back(1);
        rep(i,0,N) diff_weight.push_back(0);
    }

    ll root(ll x){
        if(x == parent[x]){
            return x;
        }else{
            ll r = root(parent[x]);
            diff_weight[x] += diff_weight[parent[x]];
            return parent[x] = r;
        }
    }

    void unite(ll a, ll b, ll w = 0){
        w += weight(a); w -= weight(b);
        a = root(a); b = root(b);
        if(a == b) return;
        parent[b] = a;
        ll sum = num[a] + num[b];
        num[a] = sum;
        num[b] = sum;
        diff_weight[b] = w;
    }

    bool same(ll a, ll b){ return root(a) == root(b);}
    
    ll sz(ll x){ return num[root(x)];}

    ll weight(ll x){
        root(x);
        return diff_weight[x];
    }

    ll diff(ll a, ll b){
        return weight(b) - weight(a);
    }
};

struct Combination{
private:
    ll N;
public:
    vector<ll> fac, facinv, inv;

    Combination(ll n){
        N = n;
        fac.resize(N+1); facinv.resize(N+1); inv.resize(N+1);
        fac[0] = fac[1] = 1;
        facinv[0] = facinv[1] = 1;
        inv[1] = 1;
        rep(i,2,N+1){
            fac[i] = fac[i-1] * i % MOD;
            inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
            facinv[i] = facinv[i-1] * inv[i] % MOD;
        }
    }

    ll power(ll x, ll n, ll m = MOD){
        if(n == 0) return 1LL;
        ll res = power(x * x % m, n/2, m);
        if(n % 2 == 1) (res *= x) %= m;
        return res;
    }

    ll nck(ll n, ll k){
        if(k == 0 || n == k) return 1LL;
        if(n < k) return 0LL;
        return fac[n] * facinv[k] % MOD * facinv[n-k] % MOD;
    }
    
    ll npk(ll n, ll k){
        if(k == 0) return 1LL;
        if(n < k) return 0LL;
        return fac[n] * facinv[n-k] % MOD;
    }
};

void solve(){
    ll N,K;
    cin >> N >> K;
    ll a[55][55];
    rep(i,0,N){
        rep(j,0,N){
            cin >> a[i][j];
        }
    }
    Combination cb(55);
    ll ans = 1;
    UnionFind uf(55);

    rep(i,0,N){
        rep(j,i+1,N){
            ll max_val = 0;
            rep(k,0,N){
                max_val = max(max_val, a[i][k] + a[j][k]);
            }
            if(max_val <= K){
                uf.unite(i, j);
            }
        }
    }
    bool check[55] = {};
    rep(i,0,N){
        ll r = uf.root(i);
        if(not check[r]){
            check[r] = true;
            ans *= cb.fac[uf.sz(r)];
            ans %= MOD;
        }
    }

    UnionFind uf2(55);

    rep(i,0,N){
        rep(j,i+1,N){
            ll max_val = 0;
            rep(k,0,N){
                max_val = max(max_val, a[k][i] + a[k][j]);
            }
            if(max_val <= K){
                uf2.unite(i, j);
            }
        }
    }
    bool check2[55] = {};
    rep(i,0,N){
        ll r = uf2.root(i);
        if(not check2[r]){
            check2[r] = true;
            ans *= cb.fac[uf2.sz(r)];
            ans %= MOD;
        }
    }
    print(ans);
    
    

}

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    solve();
}
#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;

#define fastio() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define test() int t;cin>>t;for(int test=1;test<=t;test++)
#define pb push_back
#define nl cout<<"\n"
#define all(x) x.begin(),x.end()

template<class C> void min_self( C &a, C b ){ a = min(a,b); }
template<class C> void max_self( C &a, C b ){ a = max(a,b); }

const ll MOD = 998244353;
ll mod( ll n, ll m=MOD ){ n%=m,n+=m,n%=m;return n; }

const int MAXN = 1e5+5;
const int LOGN = 21;
const ll INF = 1e14;
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};

template<class T1, class T2> void add( T1 &x, T2 y, ll m = MOD )
{
    x += y;
    if( x >= m )
        x -= m;
}

template<class T1, class T2> void sub( T1 &x, T2 y, ll m = MOD )
{
    x -= y;
    if( x < 0 )
        x += m;
}


template<class T> class Math
{
public:
    vector<T>fact,invfact;
    Math( int n )
    {
        fact.resize(n);
        invfact.resize(n);
        fact[0] = invfact[0] = 1;
        for(int i=1;i<n;i++)
        {
            fact[i] = mod( i * fact[i-1] );
            invfact[i] = modinv( fact[i] );
        }
    }
    T modinv( T x, T m = MOD )
    {
        return expo(x,m-2,m);
    }
    T expo( T base, T exp, T m = MOD )
    {
        T res = 1;
        while( exp )
        {
            if( exp&1 )
                res = mod( res*base, m );
            base = mod( base*base, m );
            exp >>= 1;
        }
        return res;
    }
    T choose( T n, T k )
    {
        if( k < 0 || k > n ) return 0;
        T ans = fact[n];
        ans = mod( ans * invfact[n-k] );
        ans = mod( ans * invfact[k] );
        return ans;
    }
};


class DSU
{
public:
    vector<int>rt,sz;
    int components;
    DSU( int n )
    {
        rt.resize(n+5);
        sz.resize(n+5);
        components = n;
        for(int i=0;i<n;i++)
        {
            rt[i] = i;
            sz[i] = 1;
        }
    }
    int get_components()
    {
        return components;
    }
    int root( int x )
    {
        while( x != rt[x] )
        {
            rt[x] = rt[rt[x]];
            x = rt[x];
        }
        return x;
    }
    void connect( int x, int y )
    {
        int r1 = root(x);
        int r2 = root(y);
        if( r1 == r2 )
            return;
        if( sz[r1] < sz[r2] )
            swap(r1,r2);
        sz[r1] += sz[r2];
        rt[r2] = r1;
        components--;
    }
};

int grid[55][55];

int main() 
{
    #ifdef gupta_samarth
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    fastio();

    int n,k;
    cin>>n>>k;

    Math<ll> m(102);

    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cin>>grid[i][j];
        }
    }

    ll ans = 1;
    for(int rep=0;rep<2;rep++)
    {
        DSU d(n);

        for(int i=0;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                int ok = 0;
                for(int ind=0;ind<n;ind++)
                {
                    if( grid[i][ind] + grid[j][ind] <= k )
                        ok++;
                }
                if( ok == n )
                    d.connect(i,j);
            }
        }

        set<int>comps;
        for(int i=0;i<n;i++)
            comps.insert(d.root(i));

        for( int x : comps )
            ans = mod( ans * m.fact[d.sz[x]] );

        // transpose
        for(int i=0;i<n;i++)
        {
            for(int j=i;j<n;j++)
            {
                swap(grid[i][j], grid[j][i]);
            }
        }
    }
    cout<<ans,nl;

    cerr << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
    return 0;
}
