#include <bits/stdc++.h>
using namespace std;
const int N = 2005;
long long tree[4 * N], tree1[4 * N], vis[N], dist[N], a[N][N], val1[N], val2[N];
long long fact[N], dp[N][N];
pair<int, int> b[N];
void build(int node, int start, int end) {
  if (start == end)
    tree[node] = 0;
  else {
    long mid = (start + end) / 2;
    build(2 * node, start, mid);
    build(2 * node + 1, mid + 1, end);
    tree[node] = tree[2 * node] + tree[2 * node + 1];
  }
}
long long int query(long node, long start, long end, long l, long r) {
  if (r < start || end < l) return 0;
  if (l <= start and end <= r) {
    return tree[node];
  }
  int mid = (start + end) / 2;
  if (r <= mid) return query(2 * node, start, mid, l, r);
  if (l >= mid + 1) return query(2 * node + 1, mid + 1, end, l, r);
  long long int p1 = query(2 * node, start, mid, l, r);
  long long int p2 = query(2 * node + 1, mid + 1, end, l, r);
  return (p1 + p2);
}
void update(long node, long start, long end, long ind, long val) {
  if (start == end) {
    tree[node] += val;
    return;
  }
  int mid = (start + end) / 2;
  if (ind <= mid)
    update(2 * node, start, mid, ind, val);
  else
    update(2 * node + 1, mid + 1, end, ind, val);
  tree[node] = tree[2 * node] + tree[2 * node + 1];
}
void build1(int node, int start, int end) {
  if (start == end)
    tree1[node] = 0;
  else {
    long mid = (start + end) / 2;
    build1(2 * node, start, mid);
    build1(2 * node + 1, mid + 1, end);
    tree1[node] = tree1[2 * node] + tree1[2 * node + 1];
  }
}
long long int query1(long node, long start, long end, long l, long r) {
  if (r < start || end < l) return 0;
  if (l <= start and end <= r) {
    return tree1[node];
  }
  int mid = (start + end) / 2;
  if (r <= mid) return query1(2 * node, start, mid, l, r);
  if (l >= mid + 1) return query1(2 * node + 1, mid + 1, end, l, r);
  long long int p1 = query1(2 * node, start, mid, l, r);
  long long int p2 = query1(2 * node + 1, mid + 1, end, l, r);
  return (p1 + p2);
}
void update1(long node, long start, long end, long ind, long val) {
  if (start == end) {
    tree1[node] += val;
    return;
  }
  int mid = (start + end) / 2;
  if (ind <= mid)
    update1(2 * node, start, mid, ind, val);
  else
    update1(2 * node + 1, mid + 1, end, ind, val);
  tree1[node] = tree1[2 * node] + tree1[2 * node + 1];
}
long long int modpow(long long int a, long long j, long long mo) {
  long long res = 1;
  while (j > 0)
    if (j & 1) {
      res = (res * a) % mo;
      --j;
    } else {
      a = (a * a) % mo;
      j >>= 1;
    }
  return res % mo;
}
long long int imodpow(long long int a, long long mo) {
  long long res = 1;
  long long j = mo - 2;
  while (j > 0)
    if (j & 1) {
      res = (res * a) % mo;
      --j;
    } else {
      a = (a * a) % mo;
      j >>= 1;
    }
  return res % mo;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin >> n;
  fact[0] = 1;
  for (int i = 1; i <= n; i++) {
    fact[i] = (1LL * i * fact[i - 1]) % 998244353;
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) cin >> a[i][j];
  }
  dp[1][1] = 0;
  dp[1][0] = 1;
  dp[0][0] = 1;
  for (int i = 2; i <= n; i++) {
    dp[i][0] = fact[i];
    for (int j = 1; j <= i; j++) {
      if (j == 1) {
        dp[i][j] = (1LL * dp[i - 1][j - 1] * (i - j)) % 998244353;
      } else {
        dp[i][j] = (1LL * dp[i - 1][j - 1] * (i - j)) % 998244353 +
                   (1LL * (j - 1LL) * (dp[i - 1][j - 2])) % 998244353;
        dp[i][j] %= 998244353;
      }
    }
  }
  long long ans = 0;
  long long dearr = modpow(dp[n][n], n - 1, 998244353);
  for (int j = 1; j <= n; j++) {
    for (int k = 1; k < a[1][j]; k++) {
      if (vis[k] == 0) {
        ans = (ans + (1LL * fact[n - j] * dearr) % 998244353) % 998244353;
      }
    }
    vis[a[1][j]] = 1;
  }
  for (int i = 2; i <= n; i++) {
    dearr = (1LL * dearr * imodpow(dp[n][n], 998244353)) % 998244353;
    for (int j = 1; j <= n; j++) dist[j] = n + 5;
    for (int j = 1; j <= n; j++) {
      dist[a[i][j]] = min(dist[a[i][j]], 1LL * j);
      dist[a[i - 1][j]] = min(dist[a[i - 1][j]], 1LL * j);
      vis[j] = 0;
    }
    int num = n;
    build(1, 1, n);
    build1(1, 1, n);
    for (int j = 1; j <= n; j++) b[j] = make_pair(a[i][j], j);
    sort(b + 1, b + n + 1);
    for (int j = 1; j <= n; j++) {
      val1[b[j].second] = query(1, 1, n, b[j].second, n);
      val2[b[j].second] = query1(1, 1, n, b[j].second, n);
      update(1, 1, n, b[j].second, 1);
      update1(1, 1, n, dist[b[j].first], 1);
      assert(b[j].second >= dist[b[j].first]);
    }
    for (int j = 1; j <= n; j++) {
      long long w1 = val1[j] - val2[j];
      long long w2 = val2[j];
      if (vis[a[i - 1][j]] == 0) {
        if (a[i - 1][j] < a[i][j]) w2--;
      }
      w1 = max(w1, 0LL);
      if (vis[a[i][j]] == 0) {
        if (vis[a[i - 1][j]] == 0) {
          w1 = (1LL * w1 * dp[n - j][num - 1]) % 998244353;
          if (num >= 3) {
            w2 = (1LL * w2 * dp[n - j][num - 2]) % 998244353;
          }
          w1 = (w1 + w2) % 998244353;
          ans = (ans + (1LL * (w1)*dearr) % 998244353) % 998244353;
          num = num - 2;
        } else {
          w1 = (1LL * w1 * dp[n - j][num]) % 998244353;
          if (num >= 2) {
            w2 = (1LL * w2 * dp[n - j][num - 1]) % 998244353;
          }
          w1 = (w1 + w2) % 998244353;
          ans = (ans + (1LL * (w1)*dearr) % 998244353) % 998244353;
          num--;
        }
      } else {
        if (vis[a[i - 1][j]] == 0) {
          w1 = (1LL * w1 * dp[n - j][num - 1]) % 998244353;
          if (num >= 2) {
            w2 = (1LL * w2 * dp[n - j][num - 2]) % 998244353;
          }
          w1 = (w1 + w2) % 998244353;
          ans = (ans + (1LL * (w1)*dearr) % 998244353) % 998244353;
          num--;
        } else {
          w1 = (1LL * w1 * dp[n - j][num]) % 998244353;
          if (num >= 1) {
            w2 = (1LL * w2 * dp[n - j][num - 1]) % 998244353;
          }
          w1 = (w1 + w2) % 998244353;
          ans = (ans + (1LL * (w1)*dearr) % 998244353) % 998244353;
        }
      }
      vis[a[i][j]] = 1;
      vis[a[i - 1][j]] = 1;
    }
  }
  cout << ans << endl;
}

### Prompt

Please create a solution in CPP 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;
const int N = 2005;
long long tree[4 * N], tree1[4 * N], vis[N], dist[N], a[N][N], val1[N], val2[N];
long long fact[N], dp[N][N];
pair<int, int> b[N];
void build(int node, int start, int end) {
  if (start == end)
    tree[node] = 0;
  else {
    long mid = (start + end) / 2;
    build(2 * node, start, mid);
    build(2 * node + 1, mid + 1, end);
    tree[node] = tree[2 * node] + tree[2 * node + 1];
  }
}
long long int query(long node, long start, long end, long l, long r) {
  if (r < start || end < l) return 0;
  if (l <= start and end <= r) {
    return tree[node];
  }
  int mid = (start + end) / 2;
  if (r <= mid) return query(2 * node, start, mid, l, r);
  if (l >= mid + 1) return query(2 * node + 1, mid + 1, end, l, r);
  long long int p1 = query(2 * node, start, mid, l, r);
  long long int p2 = query(2 * node + 1, mid + 1, end, l, r);
  return (p1 + p2);
}
void update(long node, long start, long end, long ind, long val) {
  if (start == end) {
    tree[node] += val;
    return;
  }
  int mid = (start + end) / 2;
  if (ind <= mid)
    update(2 * node, start, mid, ind, val);
  else
    update(2 * node + 1, mid + 1, end, ind, val);
  tree[node] = tree[2 * node] + tree[2 * node + 1];
}
void build1(int node, int start, int end) {
  if (start == end)
    tree1[node] = 0;
  else {
    long mid = (start + end) / 2;
    build1(2 * node, start, mid);
    build1(2 * node + 1, mid + 1, end);
    tree1[node] = tree1[2 * node] + tree1[2 * node + 1];
  }
}
long long int query1(long node, long start, long end, long l, long r) {
  if (r < start || end < l) return 0;
  if (l <= start and end <= r) {
    return tree1[node];
  }
  int mid = (start + end) / 2;
  if (r <= mid) return query1(2 * node, start, mid, l, r);
  if (l >= mid + 1) return query1(2 * node + 1, mid + 1, end, l, r);
  long long int p1 = query1(2 * node, start, mid, l, r);
  long long int p2 = query1(2 * node + 1, mid + 1, end, l, r);
  return (p1 + p2);
}
void update1(long node, long start, long end, long ind, long val) {
  if (start == end) {
    tree1[node] += val;
    return;
  }
  int mid = (start + end) / 2;
  if (ind <= mid)
    update1(2 * node, start, mid, ind, val);
  else
    update1(2 * node + 1, mid + 1, end, ind, val);
  tree1[node] = tree1[2 * node] + tree1[2 * node + 1];
}
long long int modpow(long long int a, long long j, long long mo) {
  long long res = 1;
  while (j > 0)
    if (j & 1) {
      res = (res * a) % mo;
      --j;
    } else {
      a = (a * a) % mo;
      j >>= 1;
    }
  return res % mo;
}
long long int imodpow(long long int a, long long mo) {
  long long res = 1;
  long long j = mo - 2;
  while (j > 0)
    if (j & 1) {
      res = (res * a) % mo;
      --j;
    } else {
      a = (a * a) % mo;
      j >>= 1;
    }
  return res % mo;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin >> n;
  fact[0] = 1;
  for (int i = 1; i <= n; i++) {
    fact[i] = (1LL * i * fact[i - 1]) % 998244353;
  }
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) cin >> a[i][j];
  }
  dp[1][1] = 0;
  dp[1][0] = 1;
  dp[0][0] = 1;
  for (int i = 2; i <= n; i++) {
    dp[i][0] = fact[i];
    for (int j = 1; j <= i; j++) {
      if (j == 1) {
        dp[i][j] = (1LL * dp[i - 1][j - 1] * (i - j)) % 998244353;
      } else {
        dp[i][j] = (1LL * dp[i - 1][j - 1] * (i - j)) % 998244353 +
                   (1LL * (j - 1LL) * (dp[i - 1][j - 2])) % 998244353;
        dp[i][j] %= 998244353;
      }
    }
  }
  long long ans = 0;
  long long dearr = modpow(dp[n][n], n - 1, 998244353);
  for (int j = 1; j <= n; j++) {
    for (int k = 1; k < a[1][j]; k++) {
      if (vis[k] == 0) {
        ans = (ans + (1LL * fact[n - j] * dearr) % 998244353) % 998244353;
      }
    }
    vis[a[1][j]] = 1;
  }
  for (int i = 2; i <= n; i++) {
    dearr = (1LL * dearr * imodpow(dp[n][n], 998244353)) % 998244353;
    for (int j = 1; j <= n; j++) dist[j] = n + 5;
    for (int j = 1; j <= n; j++) {
      dist[a[i][j]] = min(dist[a[i][j]], 1LL * j);
      dist[a[i - 1][j]] = min(dist[a[i - 1][j]], 1LL * j);
      vis[j] = 0;
    }
    int num = n;
    build(1, 1, n);
    build1(1, 1, n);
    for (int j = 1; j <= n; j++) b[j] = make_pair(a[i][j], j);
    sort(b + 1, b + n + 1);
    for (int j = 1; j <= n; j++) {
      val1[b[j].second] = query(1, 1, n, b[j].second, n);
      val2[b[j].second] = query1(1, 1, n, b[j].second, n);
      update(1, 1, n, b[j].second, 1);
      update1(1, 1, n, dist[b[j].first], 1);
      assert(b[j].second >= dist[b[j].first]);
    }
    for (int j = 1; j <= n; j++) {
      long long w1 = val1[j] - val2[j];
      long long w2 = val2[j];
      if (vis[a[i - 1][j]] == 0) {
        if (a[i - 1][j] < a[i][j]) w2--;
      }
      w1 = max(w1, 0LL);
      if (vis[a[i][j]] == 0) {
        if (vis[a[i - 1][j]] == 0) {
          w1 = (1LL * w1 * dp[n - j][num - 1]) % 998244353;
          if (num >= 3) {
            w2 = (1LL * w2 * dp[n - j][num - 2]) % 998244353;
          }
          w1 = (w1 + w2) % 998244353;
          ans = (ans + (1LL * (w1)*dearr) % 998244353) % 998244353;
          num = num - 2;
        } else {
          w1 = (1LL * w1 * dp[n - j][num]) % 998244353;
          if (num >= 2) {
            w2 = (1LL * w2 * dp[n - j][num - 1]) % 998244353;
          }
          w1 = (w1 + w2) % 998244353;
          ans = (ans + (1LL * (w1)*dearr) % 998244353) % 998244353;
          num--;
        }
      } else {
        if (vis[a[i - 1][j]] == 0) {
          w1 = (1LL * w1 * dp[n - j][num - 1]) % 998244353;
          if (num >= 2) {
            w2 = (1LL * w2 * dp[n - j][num - 2]) % 998244353;
          }
          w1 = (w1 + w2) % 998244353;
          ans = (ans + (1LL * (w1)*dearr) % 998244353) % 998244353;
          num--;
        } else {
          w1 = (1LL * w1 * dp[n - j][num]) % 998244353;
          if (num >= 1) {
            w2 = (1LL * w2 * dp[n - j][num - 1]) % 998244353;
          }
          w1 = (w1 + w2) % 998244353;
          ans = (ans + (1LL * (w1)*dearr) % 998244353) % 998244353;
        }
      }
      vis[a[i][j]] = 1;
      vis[a[i - 1][j]] = 1;
    }
  }
  cout << ans << endl;
}

```