//package Qo
import java.util.*
import java.math.*
import java.lang.Math.*

private val readString: ()->String = {readLine()!!}
private val readInt: ()->Int = {readLine()!!.toInt()}
private val readLong: ()->Long = {readLine()!!.toLong()}
private val readIntArray: ()->IntArray = {readLine()!!.split(' ').map{it.toInt()}.toIntArray()}
private val readLongArray: ()->LongArray = {readLine()!!.split(' ').map{it.toLong()}.toLongArray()}
private val errPrintln: (String)->Unit = {msg -> System.err.println(msg)}
private val MOD = 1e9.toLong()+7
private val INF = Int.MAX_VALUE/2
private val LINF = Long.MAX_VALUE/2


fun solveO(A: Array<IntArray>): Long {
    val N = A.size

    //val dp = Array(N+1){LongArray(0b01 shl N){0}}
    // dp[i][j] := [0,i) までの男が女と組み、女の選択状態が j となる通り数
    var dp = LongArray(0b01 shl N){0}

    //dp[0][0] = 1L
    dp[0] = 1L
    for (i in 0 until N) {
        val ndp = LongArray(0b01 shl N){0}

        for (j in 0 until (0b01 shl N)) {
            //if (dp[i][j] == 0L) continue
            if (dp[j] == 0L) continue

            for (k in 0 until N) {
                if (A[i][k] == 0) continue

                if ((j shr k) and 0b01 == 1) continue

                val nj = j or (0b01 shl k)
                //dp[i+1][nj] += dp[i][j]
                //dp[i+1][nj] %= MOD
                ndp[nj] += dp[j]
                ndp[nj] %= MOD
            }
        }
        dp = ndp
    }

    //return dp[N][(0b01 shl N)-1]
    return dp[(0b01 shl N)-1]
}


fun main(args: Array<String>) {
    val N = readInt()
    val A = Array(N){IntArray(N){0}}
    for (i in 0 until N) {
        A[i] = readIntArray()
    }

    val ans = solveO(A)

    println(ans)
}