#include <bits/stdc++.h>
using namespace std;
template <typename A, typename B>
inline void chmin(A &a, B b) {
  if (a > b) a = b;
}
template <typename A, typename B>
inline void chmax(A &a, B b) {
  if (a < b) a = b;
}
template <int64_t mod>
struct ModInt {
  int64_t a;
  inline int64_t normalize(int64_t x) {
    x %= mod;
    if (x < 0) x += mod;
    return x;
  }
  ModInt(const int64_t a = 0) : a(normalize(a)) {}
  ModInt &operator+=(const ModInt &x) {
    a += x.a;
    if (a >= mod) a -= mod;
    return *this;
  }
  ModInt &operator-=(const ModInt &x) {
    a -= x.a;
    if (a < 0) a += mod;
    return *this;
  }
  ModInt &operator*=(const ModInt &x) {
    a = a * x.a % mod;
    return *this;
  }
  ModInt &operator/=(const ModInt &x) {
    *this *= x.inv();
    return *this;
  }
  ModInt operator+(const ModInt x) { return ModInt(*this) += x; }
  ModInt operator-(const ModInt x) { return ModInt(*this) -= x; }
  ModInt operator*(const ModInt x) { return ModInt(*this) *= x; }
  ModInt operator/(const ModInt x) { return ModInt(*this) /= x; }
  bool operator==(const ModInt x) { return a == x.a; }
  bool operator!=(const ModInt x) { return a != x.a; }
  ModInt operator-() { return ModInt(0) - ModInt(*this); }
  ModInt pow(int64_t ex) const {
    int64_t x = a;
    int64_t res = 1;
    while (ex) {
      if (ex & 1) res = res * x % mod;
      x = x * x % mod;
      ex >>= 1;
    }
    return ModInt(res);
  }
  ModInt inv() const { return pow(mod - 2); }
};
using mint = ModInt<998244353>;
long long N;
vector<long long> A[2222];
mint fact[2222];
mint inv[2222];
struct BinaryIndexedTree {
  long long n;
  vector<long long> dat;
  BinaryIndexedTree(long long n = 0) : n(n) { dat.resize(n + 1); }
  void add(long long k, long long x) {
    for (k++; k <= n; k += k & -k) dat[k] += x;
  }
  long long sum(long long k) {
    long long ret = 0;
    for (k++; k; k -= k & -k) ret += dat[k];
    return ret;
  }
};
mint dp[2222][2222];
signed main() {
  scanf("%lld", &N);
  for (long long i = 0; i < (N); i++) {
    A[i].resize(N);
    for (long long j = 0; j < (N); j++) scanf("%lld", &A[i][j]), A[i][j]--;
  }
  fact[0] = mint(1);
  for (long long i = 1; i < 2222; i++) fact[i] = fact[i - 1] * i;
  inv[2222 - 1] = fact[2222 - 1].inv();
  for (long long i = 2222 - 2; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1);
  dp[0][0] = mint(1);
  for (long long i = 1; i < 2222; i++) {
    for (long long j = 0; j <= i; j++) {
      mint tmp = fact[i - j] * fact[i] * inv[j] * inv[i - j];
      if (j & 1)
        dp[i][0] -= tmp;
      else
        dp[i][0] += tmp;
    }
  }
  for (long long i = 1; i < 2222; i++) {
    for (long long j = 1; j <= i; j++) {
      dp[i][j] += dp[i - 1][j - 1] * j;
      dp[i][j] += dp[i - 1][j] * (i - j);
    }
  }
  mint ans;
  for (long long i = 0; i < N; i++) {
    BinaryIndexedTree bit(N);
    BinaryIndexedTree bit2(N);
    mint le;
    vector<long long> pre(N), cur(N), al(N);
    long long num = 0;
    if (i == 0) {
      for (long long j = 0; j < N; j++) {
        le += fact[N - 1 - j] * (A[i][j] - bit.sum(A[i][j] - 1));
        bit.add(A[i][j], 1);
      }
    } else {
      for (long long j = 0; j < N; j++) {
        long long tmp = bit2.sum(A[i][j] - 1);
        long long co = 2 * j - num;
        if (cur[A[i - 1][j]]) co++;
        le += dp[N - 1 - j][j - co] * tmp;
        tmp = A[i][j] - bit.sum(A[i][j] - 1) - tmp;
        if (A[i - 1][j] < A[i][j] && cur[A[i - 1][j]] == 0) tmp--;
        le += dp[N - 1 - j][j - co + 1] * tmp;
        if (pre[A[i][j]]) {
          bit2.add(A[i][j], -1);
        }
        cur[A[i][j]] = 1;
        if (cur[A[i - 1][j]] == 0) {
          bit2.add(A[i - 1][j], 1);
        }
        pre[A[i - 1][j]] = 1;
        if (al[A[i][j]] == 0) {
          al[A[i][j]] = 1;
          num++;
        }
        if (al[A[i - 1][j]] == 0) {
          al[A[i - 1][j]] = 1;
          num++;
        }
        bit.add(A[i][j], 1);
      }
    }
    ans += le * dp[N][0].pow(N - 1 - i);
  }
  printf("%lld\n", ans.a);
  return 0;
}

### Prompt

Generate a CPP solution to the following problem:

Petya collects beautiful matrix.

A matrix of size n × n is beautiful if: 

  * All elements of the matrix are integers between 1 and n; 
  * For every row of the matrix, all elements of this row are different; 
  * For every pair of vertically adjacent elements, these elements are different. 



Today Petya bought a beautiful matrix a of size n × n, and now he wants to determine its rarity.

The rarity of the matrix is its index in the list of beautiful matrices of size n × n, sorted in lexicographical order. Matrix comparison is done row by row. (The index of lexicographically smallest matrix is zero).

Since the number of beautiful matrices may be huge, Petya wants you to calculate the rarity of the matrix a modulo 998 244 353.

Input

The first line contains one integer n (1 ≤ n ≤ 2000) — the number of rows and columns in a.

Each of the next n lines contains n integers a_{i,j} (1 ≤ a_{i,j} ≤ n) — the elements of a.

It is guaranteed that a is a beautiful matrix.

Output

Print one integer — the rarity of matrix a, taken modulo 998 244 353.

Examples

Input


2
2 1
1 2


Output


1


Input


3
1 2 3
2 3 1
3 1 2


Output


1


Input


3
1 2 3
3 1 2
2 3 1


Output


3

Note

There are only 2 beautiful matrices of size 2 × 2:

<image>

There are the first 5 beautiful matrices of size 3 × 3 in lexicographical order:

<image>

### Response

```cpp
#include <bits/stdc++.h>
using namespace std;
template <typename A, typename B>
inline void chmin(A &a, B b) {
  if (a > b) a = b;
}
template <typename A, typename B>
inline void chmax(A &a, B b) {
  if (a < b) a = b;
}
template <int64_t mod>
struct ModInt {
  int64_t a;
  inline int64_t normalize(int64_t x) {
    x %= mod;
    if (x < 0) x += mod;
    return x;
  }
  ModInt(const int64_t a = 0) : a(normalize(a)) {}
  ModInt &operator+=(const ModInt &x) {
    a += x.a;
    if (a >= mod) a -= mod;
    return *this;
  }
  ModInt &operator-=(const ModInt &x) {
    a -= x.a;
    if (a < 0) a += mod;
    return *this;
  }
  ModInt &operator*=(const ModInt &x) {
    a = a * x.a % mod;
    return *this;
  }
  ModInt &operator/=(const ModInt &x) {
    *this *= x.inv();
    return *this;
  }
  ModInt operator+(const ModInt x) { return ModInt(*this) += x; }
  ModInt operator-(const ModInt x) { return ModInt(*this) -= x; }
  ModInt operator*(const ModInt x) { return ModInt(*this) *= x; }
  ModInt operator/(const ModInt x) { return ModInt(*this) /= x; }
  bool operator==(const ModInt x) { return a == x.a; }
  bool operator!=(const ModInt x) { return a != x.a; }
  ModInt operator-() { return ModInt(0) - ModInt(*this); }
  ModInt pow(int64_t ex) const {
    int64_t x = a;
    int64_t res = 1;
    while (ex) {
      if (ex & 1) res = res * x % mod;
      x = x * x % mod;
      ex >>= 1;
    }
    return ModInt(res);
  }
  ModInt inv() const { return pow(mod - 2); }
};
using mint = ModInt<998244353>;
long long N;
vector<long long> A[2222];
mint fact[2222];
mint inv[2222];
struct BinaryIndexedTree {
  long long n;
  vector<long long> dat;
  BinaryIndexedTree(long long n = 0) : n(n) { dat.resize(n + 1); }
  void add(long long k, long long x) {
    for (k++; k <= n; k += k & -k) dat[k] += x;
  }
  long long sum(long long k) {
    long long ret = 0;
    for (k++; k; k -= k & -k) ret += dat[k];
    return ret;
  }
};
mint dp[2222][2222];
signed main() {
  scanf("%lld", &N);
  for (long long i = 0; i < (N); i++) {
    A[i].resize(N);
    for (long long j = 0; j < (N); j++) scanf("%lld", &A[i][j]), A[i][j]--;
  }
  fact[0] = mint(1);
  for (long long i = 1; i < 2222; i++) fact[i] = fact[i - 1] * i;
  inv[2222 - 1] = fact[2222 - 1].inv();
  for (long long i = 2222 - 2; i >= 0; i--) inv[i] = inv[i + 1] * (i + 1);
  dp[0][0] = mint(1);
  for (long long i = 1; i < 2222; i++) {
    for (long long j = 0; j <= i; j++) {
      mint tmp = fact[i - j] * fact[i] * inv[j] * inv[i - j];
      if (j & 1)
        dp[i][0] -= tmp;
      else
        dp[i][0] += tmp;
    }
  }
  for (long long i = 1; i < 2222; i++) {
    for (long long j = 1; j <= i; j++) {
      dp[i][j] += dp[i - 1][j - 1] * j;
      dp[i][j] += dp[i - 1][j] * (i - j);
    }
  }
  mint ans;
  for (long long i = 0; i < N; i++) {
    BinaryIndexedTree bit(N);
    BinaryIndexedTree bit2(N);
    mint le;
    vector<long long> pre(N), cur(N), al(N);
    long long num = 0;
    if (i == 0) {
      for (long long j = 0; j < N; j++) {
        le += fact[N - 1 - j] * (A[i][j] - bit.sum(A[i][j] - 1));
        bit.add(A[i][j], 1);
      }
    } else {
      for (long long j = 0; j < N; j++) {
        long long tmp = bit2.sum(A[i][j] - 1);
        long long co = 2 * j - num;
        if (cur[A[i - 1][j]]) co++;
        le += dp[N - 1 - j][j - co] * tmp;
        tmp = A[i][j] - bit.sum(A[i][j] - 1) - tmp;
        if (A[i - 1][j] < A[i][j] && cur[A[i - 1][j]] == 0) tmp--;
        le += dp[N - 1 - j][j - co + 1] * tmp;
        if (pre[A[i][j]]) {
          bit2.add(A[i][j], -1);
        }
        cur[A[i][j]] = 1;
        if (cur[A[i - 1][j]] == 0) {
          bit2.add(A[i - 1][j], 1);
        }
        pre[A[i - 1][j]] = 1;
        if (al[A[i][j]] == 0) {
          al[A[i][j]] = 1;
          num++;
        }
        if (al[A[i - 1][j]] == 0) {
          al[A[i - 1][j]] = 1;
          num++;
        }
        bit.add(A[i][j], 1);
      }
    }
    ans += le * dp[N][0].pow(N - 1 - i);
  }
  printf("%lld\n", ans.a);
  return 0;
}

```