#include <bits/stdc++.h>
using namespace std;
const int max_n = 2022, inf = 1000111222;
const int mod = 998244353;
int mul(int x, int y) { return (1LL * x * y) % mod; }
int power(int a, int b) {
  if (b == 0) {
    return 1 % mod;
  }
  if (b % 2 == 0) {
    return power(mul(a, a), b / 2);
  }
  return mul(a, power(a, b - 1));
}
int inv(int x) { return power(x, mod - 2); }
const int max_f = 2022;
int f[max_f], rf[max_f];
void get_all_f() {
  f[0] = rf[0] = 1;
  for (int i = 1; i < max_f; ++i) {
    f[i] = mul(i, f[i - 1]);
  }
  rf[max_f - 1] = inv(f[max_f - 1]);
  for (int i = max_f - 2; i > 0; --i) {
    rf[i] = mul(i + 1, rf[i + 1]);
  }
}
int get_c(int n, int k) {
  if (n < k) {
    return 0;
  }
  return mul(f[n], mul(rf[k], rf[n - k]));
}
int n, ans, a[max_n][max_n], Used[max_n];
int get_order(int a[max_n]) {
  int res = 0;
  memset(Used, 0, sizeof(Used));
  for (int i = 0; i < n; ++i) {
    int cnt = 0;
    for (int j = 0; j < a[i]; ++j) {
      cnt += 1 - Used[j];
    }
    res += mul(cnt, f[n - 1 - i]);
    res %= mod;
    Used[a[i]] = 1;
  }
  return res;
}
int Y[max_n][max_n], pos[max_n];
struct tree {
  int t[max_n];
  void add(int i, int x) {
    for (; i < max_n; i = (i | (i + 1))) {
      t[i] += x;
    }
  }
  int get_sum(int r) const {
    int res = 0;
    for (; r >= 0; r = (r & (r + 1)) - 1) {
      res += t[r];
    }
    return res;
  }
  int get_sum(int l, int r) const {
    if (l == 0) {
      return get_sum(r);
    }
    return get_sum(r) - get_sum(l - 1);
  }
  bool find(int x) const { return get_sum(x, x) == 1; }
  void clr() { memset(t, 0, sizeof(t)); }
};
tree used, more;
int calc_x(int n) {
  int res = 0;
  for (int i = 0; i <= n; ++i) {
    int add = mul(get_c(n, i), f[n - i]);
    if (i % 2) {
      add = mod - add;
    }
    res += add;
    res %= mod;
  }
  return res;
}
int main() {
  get_all_f();
  scanf("%d", &n);
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      scanf("%d", &a[i][j]);
      --a[i][j];
    }
  }
  int X = calc_x(n);
  int order1 = get_order(a[0]);
  int ans = mul(order1, power(X, n - 1));
  for (int cnt = 0; cnt < n; ++cnt) {
    Y[cnt][0] = calc_x(cnt);
    for (int occ = 1; occ <= cnt; ++occ) {
      Y[cnt][occ] = (Y[cnt][occ - 1] + Y[cnt - 1][occ - 1]) % mod;
    }
  }
  for (int i = 1; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      pos[a[i - 1][j]] = j;
    }
    int occ = 0;
    int add = 0;
    used.clr();
    more.clr();
    for (int x = 0; x < n; ++x) {
      if (pos[x] > 0) {
        more.add(x, 1);
      }
    }
    for (int j = 0; j < n; ++j) {
      int cnt_more = more.get_sum(a[i][j] - 1);
      int cnt_used = used.get_sum(a[i][j] - 1);
      if (a[i - 1][j] < a[i][j]) {
        if (more.find(a[i - 1][j])) {
          --cnt_more;
        }
        if (used.find(a[i - 1][j])) {
          --cnt_used;
        }
      }
      int cnt_not_more = a[i][j] - cnt_more - cnt_used;
      if (a[i - 1][j] < a[i][j]) {
        --cnt_not_more;
      }
      add += mul(cnt_more, Y[n - j - 1][occ + 1]);
      add %= mod;
      add += mul(cnt_not_more, Y[n - j - 1][occ]);
      add %= mod;
      if (more.find(a[i][j])) {
        more.add(a[i][j], -1);
      }
      if (more.find(a[i - 1][j + 1])) {
        more.add(a[i - 1][j + 1], -1);
      }
      used.add(a[i][j], 1);
      if (pos[a[i][j]] > j) {
        ++occ;
      }
      if (used.find(a[i - 1][j + 1])) {
        --occ;
      }
    }
    ans += mul(add, power(X, n - i - 1));
    ans %= mod;
  }
  printf("%d\n", ans);
  return 0;
}

### Prompt

In cpp, your task is to solve 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;
const int max_n = 2022, inf = 1000111222;
const int mod = 998244353;
int mul(int x, int y) { return (1LL * x * y) % mod; }
int power(int a, int b) {
  if (b == 0) {
    return 1 % mod;
  }
  if (b % 2 == 0) {
    return power(mul(a, a), b / 2);
  }
  return mul(a, power(a, b - 1));
}
int inv(int x) { return power(x, mod - 2); }
const int max_f = 2022;
int f[max_f], rf[max_f];
void get_all_f() {
  f[0] = rf[0] = 1;
  for (int i = 1; i < max_f; ++i) {
    f[i] = mul(i, f[i - 1]);
  }
  rf[max_f - 1] = inv(f[max_f - 1]);
  for (int i = max_f - 2; i > 0; --i) {
    rf[i] = mul(i + 1, rf[i + 1]);
  }
}
int get_c(int n, int k) {
  if (n < k) {
    return 0;
  }
  return mul(f[n], mul(rf[k], rf[n - k]));
}
int n, ans, a[max_n][max_n], Used[max_n];
int get_order(int a[max_n]) {
  int res = 0;
  memset(Used, 0, sizeof(Used));
  for (int i = 0; i < n; ++i) {
    int cnt = 0;
    for (int j = 0; j < a[i]; ++j) {
      cnt += 1 - Used[j];
    }
    res += mul(cnt, f[n - 1 - i]);
    res %= mod;
    Used[a[i]] = 1;
  }
  return res;
}
int Y[max_n][max_n], pos[max_n];
struct tree {
  int t[max_n];
  void add(int i, int x) {
    for (; i < max_n; i = (i | (i + 1))) {
      t[i] += x;
    }
  }
  int get_sum(int r) const {
    int res = 0;
    for (; r >= 0; r = (r & (r + 1)) - 1) {
      res += t[r];
    }
    return res;
  }
  int get_sum(int l, int r) const {
    if (l == 0) {
      return get_sum(r);
    }
    return get_sum(r) - get_sum(l - 1);
  }
  bool find(int x) const { return get_sum(x, x) == 1; }
  void clr() { memset(t, 0, sizeof(t)); }
};
tree used, more;
int calc_x(int n) {
  int res = 0;
  for (int i = 0; i <= n; ++i) {
    int add = mul(get_c(n, i), f[n - i]);
    if (i % 2) {
      add = mod - add;
    }
    res += add;
    res %= mod;
  }
  return res;
}
int main() {
  get_all_f();
  scanf("%d", &n);
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      scanf("%d", &a[i][j]);
      --a[i][j];
    }
  }
  int X = calc_x(n);
  int order1 = get_order(a[0]);
  int ans = mul(order1, power(X, n - 1));
  for (int cnt = 0; cnt < n; ++cnt) {
    Y[cnt][0] = calc_x(cnt);
    for (int occ = 1; occ <= cnt; ++occ) {
      Y[cnt][occ] = (Y[cnt][occ - 1] + Y[cnt - 1][occ - 1]) % mod;
    }
  }
  for (int i = 1; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      pos[a[i - 1][j]] = j;
    }
    int occ = 0;
    int add = 0;
    used.clr();
    more.clr();
    for (int x = 0; x < n; ++x) {
      if (pos[x] > 0) {
        more.add(x, 1);
      }
    }
    for (int j = 0; j < n; ++j) {
      int cnt_more = more.get_sum(a[i][j] - 1);
      int cnt_used = used.get_sum(a[i][j] - 1);
      if (a[i - 1][j] < a[i][j]) {
        if (more.find(a[i - 1][j])) {
          --cnt_more;
        }
        if (used.find(a[i - 1][j])) {
          --cnt_used;
        }
      }
      int cnt_not_more = a[i][j] - cnt_more - cnt_used;
      if (a[i - 1][j] < a[i][j]) {
        --cnt_not_more;
      }
      add += mul(cnt_more, Y[n - j - 1][occ + 1]);
      add %= mod;
      add += mul(cnt_not_more, Y[n - j - 1][occ]);
      add %= mod;
      if (more.find(a[i][j])) {
        more.add(a[i][j], -1);
      }
      if (more.find(a[i - 1][j + 1])) {
        more.add(a[i - 1][j + 1], -1);
      }
      used.add(a[i][j], 1);
      if (pos[a[i][j]] > j) {
        ++occ;
      }
      if (used.find(a[i - 1][j + 1])) {
        --occ;
      }
    }
    ans += mul(add, power(X, n - i - 1));
    ans %= mod;
  }
  printf("%d\n", ans);
  return 0;
}

```