#pragma GCC optimize("O3")
#include <bits/stdc++.h>
using namespace std;

#define N 200100
#define MOD 1000000007  //998244353
#define ll long long
#define rep(i, n) for(int i = 0; i < n; ++i)
#define rep2(i, a, b) for(int i = a; i <= b; ++i)
#define rep3(i, a, b) for(int i = a; i >= b; --i)
#define eb emplace_back
#define pb push_back
#define all(c) (c).begin(), (c).end()
#define vi vector<int>
#define pii pair<int,int>
#define pll pair<ll,ll>
struct Setup_io {
	Setup_io() {
		ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
		cout << fixed << setprecision(15);
	}
} setup_io;



int main() {
	int n;
	ll a[N];
	ll b[N];
	ll c[N];
	ll x = 0;
	cin >> n;
	rep(i, n) {
		cin >> a[i];
	}
	rep(i, n) {
		cin >> b[i];
	}
	rep(i, n) {
		x = max(x, a[i]);
		if (i == 0)c[0] = a[0] * b[0];
		else c[i] = max(c[i - 1], x*b[i]);
	}
	rep(i, n) {
		cout << c[i]<<endl;
	}
	return 0;
}

#include <bits/stdc++.h>
#define rep(i,n) for (int i=0; i<(n); ++i)
#define all(a) a.begin(), a.end()
using namespace std;
using P  = pair<int, int>;
using ll = long long;
using vi = vector<int>;
using vv = vector<vi>;
//const int mod = 1000000007;
const int mod = 998244353;

struct UnionFind{
    vector<int> d;
    UnionFind(int n=0): d(n, -1) {}
    int root(int x){
        if(d[x]<0)return x;
        return d[x] = root(d[x]);
    }
    bool unite(int x, int y){
        x = root(x); y = root(y);
        if(x==y) return false;
        if(d[x]>d[y]) swap(x,y);
        d[x] += d[y]; d[y] = x;
        return true;
    }
    bool same(int x, int y){return root(x) == root(y);}
    int size(int x){return -d[root(x)];}
};

vector<ll> fac(51);

void fac_init(){
    fac[0] = 1;
    for(ll i=1; i<=50; i++){
        fac[i] = fac[i-1] * i % mod;
    }
}

int main(){
    fac_init();
    int n, k;
    cin >> n >> k;
    vv a(n, vi (n));
    rep(i,n)rep(j,n)cin >> a[i][j];
    
    UnionFind uf1(n), uf2(n);
    
    for(int x=0; x<n; x++){
        for(int y=x+1; y<n; y++){
            bool ok = true;
            rep(i,n)if(a[i][x]+a[i][y]>k)ok = false;
            if(ok)uf1.unite(x,y);
        }
    }
    for(int x=0; x<n; x++){
        for(int y=x+1; y<n; y++){
            bool ok = true;
            rep(i,n)if(a[x][i]+a[y][i]>k)ok = false;
            if(ok)uf2.unite(x,y);
        }
    }
    
    vi check1(n, 0), check2(n, 0);
    ll ans = 1;
    
    rep(i,n){
        if(check1[uf1.root(i)])continue;
        check1[uf1.root(i)] = 1;
        ans *= fac[uf1.size(i)];
        ans %= mod;
    }
    rep(i,n){
        if(check2[uf2.root(i)])continue;
        check2[uf2.root(i)] = 1;
        ans *= fac[uf2.size(i)];
        ans %= mod;
    }
    cout << ans << endl;
    return 0;
}