#include <bits/stdc++.h>
#define fi first
#define se second
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define rrep(i,n) for(int i = 1; i <= (n); ++i)
#define drep(i,n) for(int i = (n)-1; i >= 0; --i)
#define srep(i,s,t) for (int i = s; i < t; ++i)
#define rng(a) a.begin(),a.end()
#define rrng(a) a.rbegin(),a.rend()
#define maxs(x,y) (x = max(x,y))
#define mins(x,y) (x = min(x,y))
#define limit(x,l,r) max(l,min(x,r))
#define lims(x,l,r) (x = max(l,min(x,r)))
#define isin(x,l,r) ((l) <= (x) && (x) < (r))
#define pb push_back
#define eb emplace_back
#define sz(x) (int)(x).size()
#define pcnt __builtin_popcountll
#define uni(x) x.erase(unique(rng(x)),x.end())
#define show(x) cout<<#x<<" = "<<x<<endl;
#define print(x)cout<<x<<endl;
#define PQ(T) priority_queue<T,v(T),greater<T> >
#define bn(x) ((1<<x)-1)
#define dup(x,y) (((x)+(y)-1)/(y))
#define newline puts("")
#define v(T) vector<T>
#define vv(T) v(v(T))
using namespace std;
typedef long long int ll;
typedef unsigned uint;
typedef unsigned long long ull;
typedef pair<int,int> P;
typedef tuple<int,int,int> T;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<P> vp;
typedef vector<T> vt;

struct UnionFind {
  vector< int > data;
 
  UnionFind(int sz) {
    data.assign(sz, -1);
  }
  int root(int x) {
        if (data[x] < 0) return x;
        else return data[x] = root(data[x]);
  }
  bool same(int x, int y) {
    return root(x) == root(y);
  }
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if(x == y) return (false);
    if(data[x] > data[y]) swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return (true);
  }
 
  int find(int k) {
    if(data[k] < 0) return (k);
    return (data[k] = find(data[k]));
  }
 
  int size(int k) {
    return (-data[find(k)]);
  }
};

int A[55][55];
const ll mod = 998244353;
int main() {
  int n,m;
  cin >> n >> m;
  rep(i,n) rep(j,n)cin >> A[i][j];
  UnionFind R(n),C(n);
  
  rep(i,n){
    rep(j,n){
      bool ok1 = true, ok2 = true;
      rep(k,n){
        ok1&=(A[i][k]+A[j][k]<=m);
        ok2&=(A[k][i]+A[k][j]<=m);
      }
      if(ok1)R.unite(i,j);
      if(ok2)C.unite(i,j);
    }
  }
  ll a = 1,b = 1;
  for(auto v:R.data){
    if(v<0){
      ll x = -v,tmp = 1;
      while(x>=1){
        tmp*=x;
        tmp%=mod;
        x--;
      }
      a*=tmp;
      a%=mod;
    }
  }
  for(auto v:C.data){
    if(v<0){
      ll x = -v,tmp = 1;
      while(x>=1){
        tmp*=x;
        tmp%=mod;
        x--;
      }
      b*=tmp;
      b%=mod;
    }
  }
  ll ans = (a*b)%mod;
  cout<<ans<<endl;
  return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <string>
#include <map>
#include <set>
#include <stack>
#include <tuple>
#include <deque>
#include <array>
#include <numeric>
#include <bitset>
#include <iomanip>
#include <cassert>
#include <chrono>
#include <random>
#include <limits>
#include <iterator>
#include <functional>
#include <sstream>
#include <fstream>
#include <complex>
#include <cstring>
#include <unordered_map>
using namespace std;

template <class T, class U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
    return os << '(' << p.first << ", " << p.second << ')';
}

template <class Tuple, std::size_t... Is>
void tuple_out(std::ostream& os, const Tuple& tp, std::index_sequence<Is...>) {
    ((os << (Is ? ", " : "(") << std::get<Is>(tp)), ...) << ')';
}

template <class... Args>
std::ostream& operator<<(std::ostream& os, const std::tuple<Args...>& tp) {
    tuple_out(os, tp, std::index_sequence_for<Args...>{});
    return os;
}

template <class T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec) {
    int n = 0;
    for(auto e : vec)   os << (n++ ? ", " : "(") << e;
    return os << (n ? ")" : "{}");
}

template <class T, class Compare>
std::ostream& operator<<(std::ostream& os, const std::set<T, Compare>& st) {
    int n = 0;
    for(auto e : st)    os << (n++ ? ", " : "(") << e;
    return os << (n ? ")" : "{}");
}

template<class T, class U, class Compare>
std::ostream& operator<<(std::ostream& os, const std::map<T, U, Compare>& mp) {
    int n = 0;
    for(auto e : mp)    os << (n++ ? ", " : "(") << e;
    return os << (n ? ")" : "{}");
}

#ifdef LOCAL
#define debug(...) std::cout << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__)
#else
#define debug(...) void(0)
#endif

void debug_out() { std::cout << '\n'; }

template <class Head, class... Tail>
void debug_out(Head&& head, Tail&&... tail) {
    std::cout << head;
    if(sizeof...(Tail) != 0)    std::cout << ", ";
    debug_out(std::forward<Tail>(tail)...);
}

using ll = long long;
using P = pair<int, int>;
constexpr int INF = 1001001001;
constexpr int mod = 1000000007;
// constexpr int mod = 998244353;

template<class T>
inline bool chmax(T& x, T y){
    if(x < y){
        x = y;
        return true;
    }
    return false;
}
template<class T>
inline bool chmin(T& x, T y){
    if(x > y){
        x = y;
        return true;
    }
    return false;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, T;
    cin >> N >> T;
    vector<ll> A(N);
    for(int i = 0; i < N; ++i)  cin >> A[i];
    vector<ll> dat(1, 0LL);
    int M = N / 2;
    for(int mask = 0; mask < 1 << M; ++mask){
        ll sum = 0;
        for(int i = 0; i < M; ++i){
            if(mask >> i & 1)   sum += A[i];
        }
        // cout << sum << ' ';
        if(sum <= T)    dat.emplace_back(sum);
    }
    // cout << '\n';
    sort(dat.begin(), dat.end());
    dat.erase(unique(dat.begin(), dat.end()), dat.end());
    // for(auto x : dat)   cout << x << ' ';
    // cout << '\n';
    ll ans = 0;
    //cout << N - M << '\n';
    for(int mask = 0; mask < (1 << (N - M)); ++mask){
        //cout << mask << ' ';
        ll sum = 0;
        for(int i = 0; i < N - M; ++i){
            //if(mask >> i & 1)   cout << i << '\n';
            if(mask >> i & 1)   sum += A[M + i];
        }
        //cout << sum << ' ';
        if(sum > T) continue;
        auto it = upper_bound(dat.begin(), dat.end(), T - sum);
        it = prev(it);
        chmax(ans, sum + *it);
    }
    //cout << '\n';
    cout << ans << endl;
}