← Home
package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var scanner *bufio.Scanner

func init() {
	scanner = bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 1024*1024), 1024*1024*10)
}

func readInt() int {
	scanner.Scan()
	v, _ := strconv.Atoi(scanner.Text())
	return v
}

const MOD = 998244353

type BIT struct {
	tree []int
	n    int
}

func NewBIT(n int) *BIT {
	return &BIT{
		tree: make([]int, n+1),
		n:    n,
	}
}

func (b *BIT) Add(i, delta int) {
	for ; i <= b.n; i += i & -i {
		b.tree[i] += delta
	}
}

func (b *BIT) Query(i int) int {
	sum := 0
	for ; i > 0; i -= i & -i {
		sum += b.tree[i]
	}
	return sum
}

func main() {
	n := readInt()

	fact := make([]int, n+1)
	fact[0] = 1
	for i := 1; i <= n; i++ {
		fact[i] = (fact[i-1] * i) % MOD
	}

	W := make([][]int, n+1)
	for m := 0; m <= n; m++ {
		W[m] = make([]int, m+1)
		W[m][0] = fact[m]
		for k := 1; k <= m; k++ {
			W[m][k] = (W[m][k-1] - W[m-1][k-1] + MOD) % MOD
		}
	}

	Dn := W[n][n]

	powDn := make([]int, n+1)
	powDn[0] = 1
	for i := 1; i <= n; i++ {
		powDn[i] = (powDn[i-1] * Dn) % MOD
	}

	totalAns := 0

	P := make([]int, n+1)
	for j := 1; j <= n; j++ {
		P[j] = readInt()
	}

	ans1 := 0
	bit := NewBIT(n)
	for i := 1; i <= n; i++ {
		bit.Add(i, 1)
	}
	for j := 1; j <= n; j++ {
		val := P[j]
		c := bit.Query(val - 1)
		ans1 = (ans1 + c*fact[n-j]) % MOD
		bit.Add(val, -1)
	}
	totalAns = (ans1 * powDn[n-1]) % MOD

	for i := 2; i <= n; i++ {
		A := make([]int, n+1)
		for j := 1; j <= n; j++ {
			A[j] = readInt()
		}

		available := make([]bool, n+1)
		inF := make([]bool, n+1)
		for x := 1; x <= n; x++ {
			available[x] = true
			inF[x] = true
		}

		bit1 := NewBIT(n)
		bit2 := NewBIT(n)
		for x := 1; x <= n; x++ {
			bit1.Add(x, 1)
		}

		ansRow := 0
		for j := 1; j <= n; j++ {
			p := P[j]
			inF[p] = false
			if available[p] {
				bit1.Add(p, -1)
				bit2.Add(p, 1)
			}

			k := bit1.Query(n)
			aj := A[j]

			c1 := bit1.Query(aj - 1)
			c0 := bit2.Query(aj - 1)
			if p < aj && available[p] {
				c0--
			}

			term1 := 0
			if k-1 >= 0 {
				term1 = (c1 * W[n-j][k-1]) % MOD
			}
			term2 := (c0 * W[n-j][k]) % MOD

			ansRow = (ansRow + term1 + term2) % MOD

			available[aj] = false
			if inF[aj] {
				bit1.Add(aj, -1)
			} else {
				bit2.Add(aj, -1)
			}
		}

		totalAns = (totalAns + ansRow*powDn[n-i]) % MOD
		P = A
	}

	fmt.Println(totalAns)
}