#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353, N = 2333;
namespace {
inline int Add(int x, int y) { return (x += y) >= MOD ? x - MOD : x; }
inline int Sub(int x, int y) { return (x -= y) < 0 ? x + MOD : x; }
inline int Mul(int x, int y) { return 1LL * x * y % MOD; }
}  // namespace
int n, a[N][N], f[N][N], Ans;
bool used[N], cur[N];
struct BIT {
  int val[N], all;
  void Init(void) {
    for (int i = 1; i <= n; i++) {
      val[i] = 0;
    }
    all = 0;
  }
  void Modify(int x, int y) {
    all += y;
    for (; x <= n; x += -x & x) {
      val[x] += y;
    }
  }
  int Query(int x) {
    int ans = 0;
    for (; x; x -= -x & x) {
      ans += val[x];
    }
    return ans;
  }
} T[2];
int main(void) {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      scanf("%d", &a[i][j]);
    }
  }
  f[0][0] = 1;
  for (int i = 1; i <= n; i++) {
    f[i][0] = Mul(f[i - 1][0], i);
    for (int j = 1; j <= i; j++) {
      f[i][j] = Sub(f[i][j - 1], f[i - 1][j - 1]);
    }
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      used[j] = i > 1;
      cur[j] = false;
    }
    for (int j = 0; j <= 1; j++) {
      T[j].Init();
    }
    for (int j = 1; j <= n; j++) {
      T[used[j]].Modify(j, 1);
    }
    int now = 0;
    for (int j = 1; j <= n; j++) {
      int x = a[i - 1][j], y = a[i][j];
      if (x && !cur[x]) {
        T[used[x]].Modify(x, -1);
        used[x] = false;
        T[used[x]].Modify(x, 1);
      }
      now = Add(now, Mul(T[1].Query(y - 1), f[n - j][T[1].all - 1]));
      now = Add(now, Mul(T[0].Query(y - 1) - bool(x && x < y && !cur[x]),
                         f[n - j][T[1].all]));
      T[used[y]].Modify(y, -1);
      cur[y] = true;
    }
    for (int j = 1; j <= n - i; j++) {
      now = Mul(now, f[n][n]);
    }
    Ans = Add(Ans, now);
  }
  cout << Ans << endl;
}
