#![allow(unused_macros)]
#![allow(dead_code)]
#![allow(unused_imports)]

use text_io::*;

fn main() {
    const U_INF: usize = 1 << 60;
    const I_INF: isize = 1 << 60;

    let n: usize = read!();
    let mut compatibility = vec![vec![ModUsize::new(0); n]; n];
    for i in 0..n {
        for j in 0..n {
            let n = read!();
            compatibility[i][j] = ModUsize::new(n);
        }
    }

    let mut dp = vec![ModUsize::new(0); (1 << n) + 10];
    dp[0] = ModUsize::new(1);
    for bit in 0..1 << n {
        let now_man = (0..n).map(|k| (bit >> k) & 1 == 1).filter(|m| *m).count();
        for i in 0..n {
            if bit & (1 << i) == 0 {
                let tmp = dp[bit] * compatibility[now_man][i];
                dp[bit | 1 << i] += tmp;
            }
        }
    }

    println!("{}", dp[(1 << n) - 1]);
}

use num_integer::Integer;
use smallvec::alloc::fmt::{Display, Formatter};
use std::fmt;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};

#[derive(Copy, Clone)]
pub struct ModUsize {
    pub mod_value: usize,
    pub value: usize,
}

impl ModUsize {
    pub fn new(n: usize) -> Self {
        Self {
            mod_value: Self::mod1(),
            value: n % Self::mod1(),
        }
    }

    pub fn pow(self, n: usize) -> Self {
        if n == 0 {
            Self::new(1)
        } else if n % 2 == 0 {
            let t = self.pow(n / 2);
            t * t
        } else {
            self * self.pow(n - 1)
        }
    }

    pub fn inv(self) -> Self {
        self.pow(self.mod_value - 2)
    }

    pub fn mod1() -> usize {
        1000000007
    }

    pub fn mod2() -> usize {
        998244353
    }
}

impl Add for ModUsize {
    type Output = ModUsize;

    fn add(self, rhs: Self) -> Self::Output {
        let mut tmp = self;
        tmp.value += rhs.value;
        if tmp.value >= self.mod_value {
            tmp.value -= self.mod_value;
        }
        tmp
    }
}

impl AddAssign for ModUsize {
    fn add_assign(&mut self, rhs: Self) {
        *self = *self + rhs;
    }
}

impl Sub for ModUsize {
    type Output = ModUsize;

    fn sub(self, rhs: Self) -> Self::Output {
        let mut tmp = self;
        if tmp.value < rhs.value {
            tmp.value += self.mod_value;
        }
        tmp.value -= rhs.value;
        tmp
    }
}

impl SubAssign for ModUsize {
    fn sub_assign(&mut self, rhs: Self) {
        *self = *self - rhs;
    }
}

impl Mul for ModUsize {
    type Output = ModUsize;

    fn mul(self, rhs: Self) -> Self::Output {
        let mut tmp = self;
        tmp.value *= rhs.value;
        tmp.value %= self.mod_value;
        tmp
    }
}

impl MulAssign for ModUsize {
    fn mul_assign(&mut self, rhs: Self) {
        *self = *self * rhs;
    }
}

impl Div for ModUsize {
    type Output = ModUsize;

    fn div(self, rhs: Self) -> Self::Output {
        let mut tmp = self;
        tmp.value /= rhs.value;
        tmp.value %= self.mod_value;
        tmp
    }
}

impl DivAssign for ModUsize {
    fn div_assign(&mut self, rhs: Self) {
        *self = *self / rhs;
    }
}

impl Display for ModUsize {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.value)
    }
}


Measured memory_bytes: 34700