#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
const int MN = 2010;
int exp(int x, int n) {
  int ret = 1;
  while (n) {
    if (n & 1) ret = 1LL * ret * x % mod;
    x = 1LL * x * x % mod;
    n >>= 1;
  }
  return ret;
}
int inv(int x) { return exp(x, mod - 2); }
int fact[MN], invf[MN];
int comb(int n, int k) {
  return 1LL * fact[n] * invf[k] % mod * invf[n - k] % mod;
}
void fft(vector<int> &a, bool invert) {
  int n = a.size();
  for (int i = 1, j = 0; i < n; i++) {
    int bit = n >> 1;
    for (; j >= bit; bit >>= 1) j -= bit;
    j += bit;
    if (i < j) swap(a[i], a[j]);
  }
  for (int len = 2; len <= n; len <<= 1) {
    int wlen = exp((invert ? inv(3) : 3), mod / len);
    for (int i = 0; i < n; i += len) {
      int w = 1;
      for (int j = 0; j < len / 2; j++) {
        int u = a[i + j], v = 1LL * a[i + j + len / 2] * w % mod;
        a[i + j] = (u + v) % mod;
        a[i + j + len / 2] = (u + mod - v) % mod;
        w = 1LL * w * wlen % mod;
      }
    }
  }
  if (invert) {
    int x = inv(n);
    for (int i = 0; i < n; i++) a[i] = 1LL * a[i] * x % mod;
  }
}
void multiply(vector<int> &a, vector<int> &b, vector<int> &res) {
  int n = 1;
  while (n < max(a.size(), b.size())) n <<= 1;
  n <<= 1;
  a.resize(n);
  fft(a, false);
  b.resize(n);
  fft(b, false);
  for (int i = 0; i < n; i++) a[i] = 1LL * a[i] * b[i] % mod;
  fft(a, true);
  res = a;
}
struct Fenwick {
  vector<int> tree;
  void init() { tree = vector<int>(MN + 1, 0); }
  void upd(int x, int v) {
    for (int i = x + 1; i <= MN; i += (i & -i)) tree[i] += v;
  }
  int quer(int a) {
    int ret = 0;
    for (int i = a + 1; i >= 1; i -= (i & -i)) ret += tree[i];
    return ret;
  }
} fw1, fw2;
int N;
int A[MN][MN], f[MN];
vector<int> g[MN];
int main() {
  fact[0] = 1;
  for (int i = 1; i < MN; i++) {
    fact[i] = 1LL * fact[i - 1] * i % mod;
  }
  for (int i = 0; i < MN; i++) {
    invf[i] = inv(fact[i]);
  }
  scanf("%d", &N);
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      scanf("%d", &A[i][j]);
    }
  }
  int x = 0;
  for (int i = 0; i <= N; i++) {
    if (i % 2) {
      x += mod - 1LL * comb(N, i) * fact[N - i] % mod;
      x %= mod;
    } else {
      x += 1LL * comb(N, i) * fact[N - i] % mod;
      x %= mod;
    }
  }
  f[0] = 1;
  for (int i = 1; i < N; i++) {
    f[i] = 1LL * f[i - 1] * x % mod;
  }
  for (int i = 0; i < N; i++) {
    vector<int> a(i + 1), b(i + 1);
    for (int j = 0; j <= i; j++) {
      a[j] = invf[j];
      if (j % 2)
        b[j] = mod - 1LL * fact[i - j] * invf[j] % mod;
      else
        b[j] = 1LL * fact[i - j] * invf[j] % mod;
    }
    multiply(a, b, g[i]);
  }
  int ans = 0;
  for (int i = N - 1; i >= 1; i--) {
    vector<int> chk1(N + 1, 0), chk2(N + 1, 0);
    fw1.init();
    fw2.init();
    for (int j = 1; j <= N; j++) {
      fw1.upd(j, 1);
      fw2.upd(j, 1);
    }
    for (int j = 0; j < N - 1; j++) {
      if (!chk1[A[i - 1][j]]) {
        chk1[A[i - 1][j]] = 1;
        fw1.upd(A[i - 1][j], -1);
      }
      int tot = fw1.quer(MN - 1);
      int rem = fw1.quer(A[i][j] - 1);
      ans += 1LL * rem * fact[tot - 1] % mod * g[N - 1 - j][tot - 1] % mod *
             f[N - 1 - i] % mod;
      ans %= mod;
      ans += 1LL *
             (fw2.quer(A[i][j] - 1) -
              (!chk2[A[i - 1][j]] && A[i - 1][j] < A[i][j]) - rem) *
             fact[tot] % mod * g[N - 1 - j][tot] % mod * f[N - 1 - i] % mod;
      ans %= mod;
      if (!chk1[A[i][j]]) {
        chk1[A[i][j]] = 1;
        fw1.upd(A[i][j], -1);
      }
      chk2[A[i][j]] = 1;
      fw2.upd(A[i][j], -1);
    }
  }
  fw1.init();
  for (int i = 1; i <= N; i++) fw1.upd(i, 1);
  for (int i = 0; i < N - 1; i++) {
    ans += 1LL * fw1.quer(A[0][i] - 1) * fact[N - 1 - i] % mod * f[N - 1] % mod;
    ans %= mod;
    fw1.upd(A[0][i], -1);
  }
  printf("%d", ans);
}
