#include <bits/stdc++.h>
// clang-format off
using namespace std; using ll = int64_t; using ull = uint64_t; const ll INF = 9e18;
void print0() {}
template<typename Head,typename... Tail> void print0(Head head,Tail... tail){cout<<fixed<<setprecision(15)<<head;print0(tail...);}
void print() { print0("\n"); }
template<typename Head,typename... Tail>void print(Head head,Tail... tail){print0(head);if(sizeof...(Tail)>0)print0(" ");print(tail...);}
// clang-format on

class iunionfind {
   public:
    // 連続するuintにのみ使える。vectorであるため定数時間がとれる。
    // 基本的にこれだけあればよい。任意の構造体を扱うときは、IDと構造体のマッピングをとるvectorを別途用意する。
    // libs-test.cppの iuf_map あたりを検索。
    vector<ull> partition;
    vector<ull> rank;

    iunionfind(ull n) {
        partition.resize(n);
        rank.resize(n);
        for (ull x = 0; x < n; x++) {
            partition[x] = x;
            rank[x] = 0;
        }
    }
    ull find(ull x) {
        if (partition[x] == x) {
            return x;
        } else {
            partition[x] = find(partition[x]);
            return partition[x];
        }
    }
    void unite(ull x, ull y) {
        x = find(x);
        y = find(y);
        if (x == y) {
            return;
        }
        if (rank[x] < rank[y]) {
            partition[x] = y;
        } else {
            partition[y] = x;
            if (rank[x] == rank[y]) {
                rank[x]++;
            }
        }
    }
    bool same(ull x, ull y) {
        return find(x) == find(y);
    }
};

const ll MODULO = 998244353L;
int main() {
    ll N, K;
    cin >> N >> K;
    vector<vector<ll>> a(N, vector<ll>(N, 0));
    // vector<ll> rtotal(N, 0);
    // vector<ll> ctotal(N, 0);
    for (ll r = 0; r < N; r++) {
        for (ll c = 0; c < N; c++) {
            cin >> a[r][c];
            // rtotal[r] += a[r][c];
            // ctotal[c] += a[r][c];
        }
    }
    auto rswap = iunionfind(N);
    for (ll r = 0; r < N; r++) {
        for (ll rr = r + 1; rr < N; rr++) {
            bool swapok = true;
            for (ll c = 0; c < N; c++) {
                if (a[r][c] + a[rr][c] > K) {
                    swapok = false;
                }
            }
            if (swapok) {
                rswap.unite(r, rr);
            }
        }
    }
    auto cswap = iunionfind(N);
    for (ll c = 0; c < N; c++) {
        for (ll cc = c + 1; cc < N; cc++) {
            bool swapok = true;
            for (ll r = 0; r < N; r++) {
                if (a[r][c] + a[r][cc] > K) {
                    swapok = false;
                }
            }
            if (swapok) {
                cswap.unite(c, cc);
            }
        }
    }
    vector<ll> facttbl(N + 1, 1);
    for (ll i = 2; i <= N; i++) {
        facttbl[i] = (facttbl[i - 1] * i) % MODULO;
    }

    vector<ll> rcluster(N, 0);
    for (ll r = 0; r < N; r++) {
        rcluster[rswap.find(r)]++;
    }
    ll rnum = 1;
    for (ll r = 0; r < N; r++) {
        ll clsize = rcluster[r];
        if (clsize >= 2) {
            rnum = (rnum * facttbl[clsize]) % MODULO;
        }
    }

    vector<ll> ccluster(N, 0);
    for (ll c = 0; c < N; c++) {
        ccluster[cswap.find(c)]++;
    }
    ll cnum = 1;
    for (ll c = 0; c < N; c++) {
        ll clsize = ccluster[c];
        if (clsize >= 2) {
            cnum = (cnum * facttbl[clsize]) % MODULO;
        }
    }
    //print(cnum, rnum);
    ll ans = (rnum * cnum) % MODULO;
    //ll ans = fact(rswap + 1) * fact(cswap + 1) % MODULO;
    print(ans);
}

#define DEBUG 0

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

#if DEBUG
// basic debugging macros
int __i__,__j__;
#define printLine(l) for(__i__=0;__i__<l;__i__++){cout<<"-";}cout<<endl
#define printLine2(l,c) for(__i__=0;__i__<l;__i__++){cout<<c;}cout<<endl
#define printVar(n) cout<<#n<<": "<<n<<endl
#define printArr(a,l) cout<<#a<<": ";for(__i__=0;__i__<l;__i__++){cout<<a[__i__]<<" ";}cout<<endl
#define print2dArr(a,r,c) cout<<#a<<":\n";for(__i__=0;__i__<r;__i__++){for(__j__=0;__j__<c;__j__++){cout<<a[__i__][__j__]<<" ";}cout<<endl;}
#define print2dArr2(a,r,c,l) cout<<#a<<":\n";for(__i__=0;__i__<r;__i__++){for(__j__=0;__j__<c;__j__++){cout<<setw(l)<<setfill(' ')<<a[__i__][__j__]<<" ";}cout<<endl;}

// advanced debugging class
// debug 1,2,'A',"test";
class _Debug {
    public:
        template<typename T>
        _Debug& operator,(T val) {
            cout << val << endl;
            return *this;
        }
};
#define debug _Debug(),
#else
#define printLine(l)
#define printLine2(l,c)
#define printVar(n)
#define printArr(a,l)
#define print2dArr(a,r,c)
#define print2dArr2(a,r,c,l)
#define debug
#endif

// define
#define MAX_VAL 999999999
#define MAX_VAL_2 999999999999999999LL
#define EPS 1e-6
#define mp make_pair
#define pb push_back

// typedef
typedef unsigned int UI;
typedef long long int LLI;
typedef unsigned long long int ULLI;
typedef unsigned short int US;
typedef pair<int,int> pii;
typedef pair<LLI,LLI> plli;
typedef vector<int> vi;
typedef vector<LLI> vlli;
typedef vector<pii> vpii;
typedef vector<plli> vplli;

// ---------- END OF TEMPLATE ----------
#define MOD 998244353

int dp[3001][3001];
int main() {
    int N,K;
    cin >> N >> K;

    int i,j;
    for (i = 0; i <= N; i++) {
        for (j = 0; j <= N; j++) {
            if ((i == 0) || (j == 0)) dp[i][j] = 1;
            else {
                if (j > 1) dp[i][j] = dp[i][j-1];
                if ((i >= j) && (2*j <= N)) dp[i][j] += dp[i-j][2*j];
                if (dp[i][j] >= MOD) dp[i][j] -= MOD;
            }
        }
    }
    cout << dp[N-K][K] << endl;

    return 0;
}

