#include <bits/stdc++.h>
using namespace std;
const int maxn = 2050;
const long long MOD = 998244353;
int n, a[maxn][maxn];
long long T[maxn][maxn];
bool c1[maxn], c2[maxn];
struct Bit {
  int sum[maxn];
  void reset() { memset(sum, 0, sizeof sum); }
  void add(int x) {
    while (x <= n) sum[x]++, x += (x & -x);
  }
  int query(int x) {
    int ans = 0;
    while (x) ans += sum[x], x -= (x & -x);
    return ans;
  }
} A, B;
long long fact[maxn], rfac[maxn];
long long getInv(long long x) {
  return x == 1 ? x : getInv(MOD % x) * (MOD - MOD / x) % MOD;
}
long long C(int n, int k) {
  if (k > n) return 0;
  return fact[n] * rfac[k] % MOD * rfac[n - k] % MOD;
}
vector<int> idx;
void rev(vector<int>& a, int n) {
  if (idx.size() != n) {
    idx.assign(n, 0);
    for (int i = 0; i < n; ++i)
      idx[i] = (idx[i >> 1] >> 1) + (i & 1) * (n >> 1);
  }
  for (int i = 0; i < n; ++i)
    if (i < idx[i]) swap(a[i], a[idx[i]]);
}
long long Pow(long long x, long long n) {
  long long ans = 1, base = x % MOD;
  while (n) {
    if (n & 1) ans = ans * base % MOD;
    base = base * base % MOD;
    n >>= 1;
  }
  return ans;
}
void ntt(vector<int>& a, int n, int op) {
  rev(a, n);
  for (int l = 2; l <= n; l <<= 1) {
    long long wn = Pow(3, (MOD - 1) / l);
    if (op == -1) wn = getInv(wn);
    for (int i = 0; i < n; i += l) {
      long long w = 1;
      for (int k = i; k < i + (l >> 1); ++k) {
        long long u = a[k], v = a[k + (l >> 1)];
        a[k] = (u + v * w) % MOD;
        a[k + (l >> 1)] = (u - v * w) % MOD;
        w = w * wn % MOD;
      }
    }
  }
  if (op == -1) {
    long long t = getInv(n);
    for (int i = 0; i < n; ++i) a[i] = (long long)a[i] * t % MOD;
  }
}
void mul(vector<int>& a, vector<int>& b) {
  int N = 1;
  while (N <= a.size() + b.size() - 2) N <<= 1;
  a.resize(N), b.resize(N);
  ntt(a, N, 1), ntt(b, N, 1);
  for (int i = 0; i < N; ++i) a[i] = (long long)a[i] * b[i] % MOD;
  ntt(a, N, -1);
}
void init() {
  fact[0] = 1;
  for (int i = 1; i < maxn; ++i) fact[i] = fact[i - 1] * i % MOD;
  rfac[maxn - 1] = getInv(fact[maxn - 1]);
  for (int i = maxn - 2; i >= 0; --i) rfac[i] = rfac[i + 1] * (i + 1) % MOD;
  T[0][0] = 1;
  for (int i = 1; i <= n; ++i) {
    for (int j = 0; j <= i; ++j) {
      if (j)
        T[i][j] = (T[i][j - 1] - T[i - 1][j - 1]) % MOD;
      else
        T[i][j] = fact[i];
    }
  }
}
int main() {
  scanf("%d", &n);
  init();
  long long ans = 0;
  for (int i = 1; i <= n; ++i) {
    scanf("%d", &a[1][i]);
    int x = a[1][i];
    ans += (long long)(x - 1 - A.query(x - 1)) * fact[n - i];
    ans %= MOD;
    A.add(x);
  }
  A.reset();
  ans = ans * Pow(T[n][n], n - 1) % MOD;
  for (int i = 2; i <= n; ++i) {
    long long sum = 0;
    memset(c1, 0, sizeof c1);
    memset(c2, 0, sizeof c2);
    for (int j = 1; j <= n; ++j) {
      scanf("%d", &a[i][j]);
      int x = a[i][j], y = a[i - 1][j];
      if (c2[y]) {
        int total = x - 1 - A.query(x - 1), l = x - 1 - B.query(x - 1),
            r = total - l;
        int S = n - B.query(n);
        if (S) sum = (sum + (long long)l * T[n - j][S - 1]) % MOD;
        sum = (sum + (long long)r * T[n - j][S]) % MOD;
      } else if (x < y) {
        int total = x - 1 - A.query(x - 1), l = x - 1 - B.query(x - 1),
            r = total - l;
        int S = n - B.query(n);
        if (S >= 2) sum = (sum + (long long)l * T[n - j][S - 2]) % MOD;
        if (S) sum = (sum + (long long)r * T[n - j][S - 1]) % MOD;
      } else {
        int total = x - 1 - A.query(x - 1), l = x - 1 - B.query(x - 1),
            r = total - l;
        int S = n - B.query(n);
        --l;
        if (S >= 2) sum = (sum + (long long)l * T[n - j][S - 2]) % MOD;
        if (S) sum = (sum + (long long)r * T[n - j][S - 1]) % MOD;
      }
      A.add(x);
      if (!c1[x] && !c2[x]) B.add(x);
      if (!c1[y] && !c2[y]) B.add(y);
      c1[y] = true, c2[x] = true;
    }
    A.reset(), B.reset();
    ans = (ans + sum * Pow(T[n][n], n - i)) % MOD;
  }
  if (ans < 0) ans += MOD;
  cout << ans << endl;
  return 0;
}
