#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
#define REP(i, n) for(int i=0; i<n; i++)
#define REPi(i, a, b) for(int i=int(a); i<int(b); i++)
#define MEMS(a,b) memset(a,b,sizeof(a))
#define mp make_pair
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
const ll MOD = 998244353;

ll A[100][100];

class UnionFind{
    vector<int> par;
    vector<int> rank;
    vector<int> size;

public:
    UnionFind(int n){
        for(int i = 0; i < n; i++){
            par.push_back(i);
            rank.push_back(0);
            size.push_back(1);
        }
    }

    ll find(int x){
        if(x == par[x])
            return x;
        else
            return par[x] = find(par[x]);
    }

    void unite(int x, int y){
        x = find(x);
        y = find(y);
        if(x == y) return;
        if(rank[x] > rank[y]){
            par[y] = x;
            size[x] += size[y];
        }
        else{
            par[x] = y;
            rank[y] = max(rank[y], rank[x]+1);
            size[y] += size[x];
        }
    }

    bool same(int x, int y){
        return find(x) == find(y);
    }

    int get_size(int x){
        return size[x];
    }
};

ll N, K;
ll KJ[100100];

ll calc(UnionFind& uni){
    ll ret = 1;
    vector<bool> isvisited(N, false);
    REP(i,N){
        int parent = uni.find(i);
        if(isvisited[parent]) continue;
        int size = uni.get_size(parent);
        ret *= KJ[size];
        ret %= MOD;
        isvisited[parent] = true;
    }
    return ret;
}

int main(){
    cin >> N >> K;
    REP(i,N){
        REP(j,N){
            cin >> A[i][j];
        }
    }

    UnionFind row(N+1), col(N+1);

    ll kaijo = 1;
    REPi(i,1,N+1){
        kaijo *= i;
        kaijo %= MOD;
        KJ[i] = kaijo;
    }

    REP(i,N){
        REPi(j,i+1,N){
            bool valid = true;
            REP(k,N){
                ll sum = A[i][k] + A[j][k];
                if(sum > K)
                    valid = false;
            }
            if(!valid) continue;
            row.unite(i,j);
        }
    }

    REP(i,N){
        REPi(j,i+1,N){
            bool valid = true;
            REP(k,N){
                ll sum = A[k][i] + A[k][j];
                if(sum > K)
                    valid = false;
            }
            if(!valid) continue;
            col.unite(i,j);
        }
    }

    ll ans = 1;
    ll row_score = calc(row);
    ll col_score = calc(col);
    ans = (ans * row_score) % MOD;
    ans = (ans * col_score) % MOD;

    cout << ans << endl;
    return 0;
}

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<cmath>
#include<set>
#include<vector>

#define rep(i,a,b) for(ll i=a;i<=b;++i)
#define per(i,a,b) for(ll i=a;i>=b;--i)
#define fi first
#define se second
#define mp make_pair
#define all(x) x.begin(),x.end()
#define debug(x) cout<<# x <<" is "<<x<<endl;

using namespace std;
typedef long long ll;
typedef pair<ll,ll> PII;
const ll maxn=40+10,inf=0x3f3f3f3f3f3f3f3f,mod=1e9+7;

ll a[maxn],temp[int((1<<20)+10)];
set<ll> s1,s2;

int main()
{
	int n,t;	scanf("%d%d",&n,&t);
	rep(i,1,n) scanf("%lld",a+i);
	sort(a+1,a+1+n);

	s1.insert(0);
	rep(i,1,n/2){
		int cnt=0;
		for(auto iter=s1.begin();iter!=s1.end();iter++){
			ll num=*iter+a[i];
			if(s1.find(num)==s1.end()&&num<=t) temp[++cnt]=num;
		}
		rep(i,1,cnt) s1.insert(temp[i]);
	}

	s2.insert(0);
	rep(i,n/2+1,n){
		int cnt=0;
		for(auto iter=s2.begin();iter!=s2.end();iter++){
			ll num=*iter+a[i];
			if(s2.find(num)==s2.end()&&num<=t) temp[++cnt]=num;
		}
		rep(i,1,cnt) s2.insert(temp[i]);
	}

	//ll ans=0;
	//s1.insert(0);
	//auto iter=s2.end(),iter1=s1.begin();	iter--;
	//for(;iter!=s2.begin();iter--){
	//	auto temp=iter1;
	//	while(iter1!=s1.end()&&*iter1+*iter<=t) iter1++;
	//	//if(temp==iter1) continue;
	//	temp=iter1;	temp--;
	//	ans=max(ans,*temp+*iter);
	//}
	ll ans=0;
	s2.insert(-1);
	auto iter=s2.end(),iter1=s1.begin();	iter--;
	for(;iter!=s2.begin();iter--){
		if(*iter1+*iter>t) continue;
		else{
			while(iter1!=s1.end()&&*iter1+*iter<=t){
				ans=max(ans,*iter1+*iter);
				iter1++;
			}
			if(iter1==s1.end()) break;
		}
	}

	cout<<ans<<endl;
	return 0;
}