#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

#define sz(a) a.size()
#define all(a) a.begin(),a.end()
#define F first
#define S second
#define pb push_back
#define eb emplace_back
#define ll long long
#define vi vector<int>
#define pi pair<int,int>
#define mp make_pair



string to_string(string s) {
	return '"' + s + '"';
}

string to_string(const char* s) {
	return to_string((string) s);
}

string to_string(bool b) {
	return (b ? "true" : "false");
}

string to_string(char ch) {
	return string("'")+ch+string("'");
}

template <typename A, typename B>
string to_string(pair<A, B> p) {
	return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template <class InputIterator>
string to_string (InputIterator first, InputIterator last) {
	bool start = true;
	string res = "{";
	while (first!=last) {
		if (!start) {
			res += ", ";
		}
		start = false;
		res += to_string(*first);
		++first;
	}
	res += "}";
	return res;
}

template <typename A>
string to_string(A v) {
	bool first = true;
	string res = "{";
	for (const auto &x : v) {
		if (!first) {
			res += ", ";
		}
		first = false;
		res += to_string(x);
	}
	res += "}";
	return res;
}

void debug_out() { cerr << endl; }

template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	cerr << " " << to_string(H);
	debug_out(T...);
}

template <typename A, typename B>
istream& operator>>(istream& input,pair<A,B>& x){
	input>>x.F>>x.S;
	return input;
}

template <typename A>
istream& operator>>(istream& input,vector<A>& x){
	for(auto& i:x)
		input>>i;
	return input;
}

#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

#define int ll

const int mod=1e9+7;

int mul(int a,int b)
{
	return ((a)*1ll*(b))%mod;
	}
	
void add(int &a,int b)
{
	a+=b;
	if(a>=mod)a-=mod;
	if(a<0)a+=mod;
	}
int powz(int a,int b)
{
	int res=1;
	while(b)
	{
		if(b&1)res=mul(res,a);
		b/=2;
		a=mul(a,a);
		}
	return res;
	}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int N=3000005;

int dp[N];

void solve(){
int n;
cin>>n;
vector<vector<int>>v(n,vector<int>(n));
for(auto &i:v)cin>>i;
dp[0]=1;
for(int i=0;i<(1<<n)-1;i++)
{
	int z=__builtin_popcount(i);
	for(int j=0;j<n;j++)
	{
		if(!(i&(1<<j)))
		{
			if(v[j][z])
			add(dp[i^(1<<j)],dp[i]);
			}
		}
	}
	cout<<dp[(1<<n)-1];
}
	

signed main()
{   
    ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int tc=1;
	//cin>>tc;
	
    for(int i=0;i<tc;i++)
	{
	//	cout<<"Case #"<<i+1<<": ";
        solve();
		}
	
	}
/* Intuition > Logic 
 * If you are not confident please dont submit
 * When you feel like Quitting: Remember why you started
 * Game Theory == Skip
 * If n== 1e18 apply binary or Matrix expo

 * I see those tears in your eyes
   I feel so helpless inside
   Oh love, there's no need to hide
   Just let me love you when your heart is tired
   Cold hands, red eyes
   Packed your bags at midnight
   They've been there for weeks
   You don't know what goodbye means
   Just roll up a cigarette
   Just forget about this mess
   Waiting on the sidelines
   From the sidelines
 */


Measured memory_bytes: 18688