#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x = 0 ,w = 1;
	char c = getchar();
	while(c < '0' || c > '9'){
		if(c == '-'){
			w = -1;
			c = getchar();
		}
	}
	while(c >= '0' && c <= '9'){
		x = (x << 3) + (x << 1) + c - '0';
		c = getchar();
	}
	return x * w;
}
inline int min(int a,int b){return a < b ? a : b;}
int a,b,x,y;
int p[205][205];
int main(){
	a = read(),b = read(),x = read(),y = read();
	memset(p,0x3f,sizeof p);
	p[1][101] = p[101][1] = x;
	for(int i = 2;i <= 100;i++){
		p[i][i + 99] = p[i + 99][i] = p[i][i + 100] = p[i + 100][i] = x;
		p[i][i - 1] = p[i - 1][i] = p[i + 100][i + 99] = p[i + 99][i + 100] = y;
	}
	b += 100;
	for(int k = 1;k <= 200;k++)
	for(int i = 1;i <= 200;i++)
	for(int j = 1;j <= 200;j++){
		if(i == j) continue;
		p[i][j] = min(p[i][k] + p[k][j],p[i][j]);
	}
	printf("%d\n",min(p[a][b],p[b][a]));
	return 0;
}
#pragma GCC target ("avx2")
#pragma GCC optimize ("unroll-loops")
#pragma GCC optimize ("O3")
#include "bits/stdc++.h"
#include <unordered_set>
#include <unordered_map>
#include <random>
using namespace std;
typedef long long ll;
const ll MOD = /*1'000'000'007LL;*/ 998'244'353LL;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int (i)=0; (i)<(n); (i)++)
const int dy[4]={ -1,0,1,0 };
const int dx[4]={ 0,-1,0,1 };

struct UnionFind{
private:
    vector<int> par;
    vector<int> siz;
public:
    void init(int N){
        par.resize(N);
        siz.resize(N);
        for(int i=0; i<N; i++) par[i] = i;
        for(int i=0; i<N; i++) siz[i] = 1;
    }
    void unite(int a, int b){
        int rootA = root(a);
        int rootB = root(b);
        if(rootA == rootB) return;
        if(siz[rootA] < siz[rootB]) swap(rootA, rootB);
        par[rootB] = rootA;
        siz[rootA] += siz[rootB];
    }
    int root(int a){
        if(par[a] == a) return a;
        return par[a] = root(par[a]);
    }
    bool same(int a, int b){
        return root(a) == root(b);
    }
    int size(int a){
        return siz[root(a)];
    }
};

template<long long Mod>
struct mint{
    long long x;
    mint(long long x=0) :x((x% Mod+Mod)%Mod){}

    mint operator-() const { return mint(-x); }

    mint& operator+=(const mint a) {
        if((x += a.x) >= Mod) x -= Mod;
        return *this;
    }
    mint& operator-=(const mint a) {
        if((x += Mod-a.x) >= Mod) x -= Mod;
        return *this;
    }
    mint& operator*=(const mint a) {
        (x *= a.x) %= Mod;
        return *this;
    }

    mint operator^(long long t) const {
        mint ret(1);
        mint a = *this;
        while(t){
            if(t&1){
                ret *= a;
            }
            a *= a;
            t >>= 1;
        }
        return ret;
    }
    mint inv() const { return *this ^ (Mod-2); }
    mint& operator/=(const mint a) { return *this *= a.inv(); }

    mint operator+(const mint a) const { return mint(*this) += a; }
    mint operator-(const mint a) const { return mint(*this) -= a; }
    mint operator*(const mint a) const { return mint(*this) *= a; }
    mint operator/(const mint a) const { return mint(*this) /= a; }

    friend istream& operator>>(istream& is, mint& a) { return is >> a.x; }
    friend ostream& operator<<(ostream& os, const mint& a) { return os << a.x; }
};

int N, K;
int A[50][50];

UnionFind r, c;

mint<MOD> fact(int i){
    if(i == 0) return 1;
    return fact(i-1) * i;
}

signed main(){
    cin >> N >> K;
    rep(i, N) rep(j, N) cin >> A[i][j];

    r.init(N);
    c.init(N);
    rep(i, N){
        rep(j, N){
            bool ok = true;
            rep(k, N){
                ok &= (A[i][k] + A[j][k] <= K);
            }
            if(ok) r.unite(i, j);
            ok = true;
            rep(k, N){
                ok &= (A[k][i] + A[k][j] <= K);
            }
            if(ok) c.unite(i, j);
        }
    }

    mint<MOD> ans = 1;
    rep(i, N){
        if(c.root(i) == i){
            ans *= fact(c.size(i));
        }
        if(r.root(i) == i){
            ans *= fact(r.size(i));
        }
    }
    cout << ans << endl;
}