#include <bits/stdc++.h>
using namespace std;
const long double PI = 3.1415926535897932384626433832795L;
template <class T>
bool uin(T &, const T &);
template <class T>
bool uax(T &, const T &);
template <class T>
T gcd(T, T);
template <class T>
T lcm(T, T);
template <class _T>
inline string tostr(const _T &);
template <typename T>
void input(T &);
template <typename T = long long>
T nxt();
bool checkp(long long);
template <typename T>
T pw(T a, T n, T m);
template <typename T>
T inv(T a, T p);
template <class _T>
_T sqr(const _T &first);
int TTT;
const long long mod = 998244353;
void pre() {}
void solve(int) {
  int n = nxt();
  vector<vector<int>> a(n, vector<int>(n));
  for (int i = 0; i < (int)(n); ++i) {
    for (int j = 0; j < (int)(n); ++j) a[i][j] = nxt() - 1;
  }
  vector<vector<long long>> dp(n + 1, vector<long long>(n + 1));
  dp[0][0] = 1;
  for (int i = 1; i <= n; ++i) {
    dp[i][0] = dp[i - 1][0] * i % mod;
    dp[i][1] = (i - 1) * dp[i - 1][0] % mod;
    for (int j = 2; j <= i; ++j) {
      dp[i][j] =
          ((j - 1) * dp[i - 1][j - 2] + (i - j) * dp[i - 1][j - 1]) % mod;
    }
  }
  vector<long long> s(n);
  s[0] = 1;
  for (int i = 0; i < (int)(n - 1); ++i) {
    s[i + 1] = s[i] * dp[n][n] % mod;
  }
  vector<int> prev(n, n);
  long long answer = 0;
  vector<bitset<2001>> pref(n);
  for (int i = 0; i < (int)(n - 1); ++i) {
    pref[i + 1] = pref[i];
    pref[i + 1][i] = true;
  }
  for (int i = 0; i < (int)(n); ++i) {
    bitset<2001> was;
    bitset<2001> used;
    if (i)
      for (int first : prev) was[first] = true;
    long long Z = 0;
    for (int j = 0; j < (int)(n); ++j) {
      was[prev[j]] = false;
      size_t rem = (~used & was).count();
      auto CUR = (~used & pref[a[i][j]]);
      CUR[prev[j]] = false;
      size_t A = CUR.count();
      size_t B = (CUR & was).count();
      A -= B;
      assert(rem > 0 || B == 0);
      Z +=
          (rem > 0 ? (dp[n - j - 1][rem - 1] * B) : 0) + dp[n - j - 1][rem] * A;
      Z %= mod;
      assert(prev[j] != a[i][j]);
      used[a[i][j]] = true;
    }
    answer += Z * s[n - 1 - i];
    answer %= mod;
    prev = a[i];
  }
  cout << answer << "\n";
}
int main(int argc, char **argv) {
  ::TTT = 1;
  pre();
  for (int test = 1; test <= ::TTT; ++test) {
    solve(test);
  }
  return 0;
}
template <typename T>
T gcd(T first, T second) {
  while (second > 0) {
    first %= second;
    swap(first, second);
  }
  return first;
}
template <class T>
T lcm(T a, T b) {
  return a / gcd(a, b) * b;
}
template <class _T>
inline _T sqr(const _T &first) {
  return first * first;
}
template <class _T>
inline string tostr(const _T &a) {
  ostringstream os("");
  os << a;
  return os.str();
}
template <typename T>
inline void input(T &a) {
  static int ed;
  a = 0;
  while (!isdigit(ed = getchar()) && ed != '-') {
  }
  char neg = 0;
  if (ed == '-') {
    neg = 1;
    ed = getchar();
  }
  while (isdigit(ed)) {
    a = 10 * a + ed - '0';
    ed = getchar();
  }
  if (neg) a = -a;
}
template <typename T>
inline T nxt() {
  T res;
  input(res);
  return res;
}
void myassert(bool v) { assert(v); }
mt19937 generator;
bool checkp(long long v) {
  if (v < 2) return false;
  for (long long i = 2; i * i <= v; ++i) {
    if (v % i == 0) {
      return false;
    }
  }
  return true;
}
template <typename T>
T pw(T a, T n, T m) {
  T res = 1;
  while (n) {
    if (n & 1) {
      res = res * a % m;
    }
    a = a * a % m;
    n >>= 1;
  }
  return res;
}
template <typename T>
T inv(T a, T p) {
  T res = 1;
  while (a > 1) {
    res = res * (p - p / a) % p;
    a = p % a;
  }
  return res;
}
template <class T>
bool uin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
bool uax(T &a, const T &b) {
  if (b > a) {
    a = b;
    return true;
  }
  return false;
}
