```go
package main
import (
"bufio"
"io"
"os"
"sort"
"strconv"
)
const MOD int64 = 1000000007
type Pair struct {
g int
c int
}
func main() {
data, _ := io.ReadAll(os.Stdin)
idx := 0
nextInt := func() int {
n := 0
sign := 1
for idx < len(data) && (data[idx] < '0' || data[idx] > '9') && data[idx] != '-' {
idx++
}
if idx < len(data) && data[idx] == '-' {
sign = -1
idx++
}
for idx < len(data) && data[idx] >= '0' && data[idx] <= '9' {
n = n*10 + int(data[idx]-'0')
idx++
}
return sign * n
}
n := nextInt()
m := nextInt()
typeMap := make(map[int][]Pair, 1<<16)
for gi := 1; gi <= n; gi++ {
cnt := nextInt()
arr := make([]int, cnt)
for i := 0; i < cnt; i++ {
arr[i] = nextInt()
}
sort.Ints(arr)
for i := 0; i < cnt; {
t := arr[i]
j := i + 1
for j < cnt && arr[j] == t {
j++
}
typeMap[t] = append(typeMap[t], Pair{g: gi, c: j - i})
i = j
}
}
sigCount := make(map[string]int, len(typeMap)+1)
buf := make([]byte, 0, 32)
for _, pairs := range typeMap {
b := buf[:0]
for _, p := range pairs {
b = strconv.AppendInt(b, int64(p.g), 10)
b = append(b, '#')
b = strconv.AppendInt(b, int64(p.c), 10)
b = append(b, ';')
}
key := string(b)
sigCount[key]++
}
zeroClass := m - len(typeMap)
if zeroClass > 0 {
sigCount[""] += zeroClass
}
fact := make([]int64, m+1)
fact[0] = 1
for i := 1; i <= m; i++ {
fact[i] = fact[i-1] * int64(i) % MOD
}
ans := int64(1)
for _, cnt := range sigCount {
ans = (ans * fact[cnt]) % MOD
}
w := bufio.NewWriter(os.Stdout)
w.WriteString(strconv.FormatInt(ans, 10))
w.WriteByte('\n')
w.Flush()
}
```