using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("3");
WillReturn.Add("0 1 1");
WillReturn.Add("1 0 1");
WillReturn.Add("1 1 1");
//3
}
else if (InputPattern == "Input2") {
WillReturn.Add("4");
WillReturn.Add("0 1 0 0");
WillReturn.Add("0 0 0 1");
WillReturn.Add("1 0 0 0");
WillReturn.Add("0 0 1 0");
//1
}
else if (InputPattern == "Input3") {
WillReturn.Add("1");
WillReturn.Add("0");
//0
}
else if (InputPattern == "Input4") {
WillReturn.Add("21");
WillReturn.Add("0 0 0 0 0 0 0 1 1 0 1 1 1 1 0 0 0 1 0 0 1");
WillReturn.Add("1 1 1 0 0 1 0 0 0 1 0 0 0 0 1 1 1 0 1 1 0");
WillReturn.Add("0 0 1 1 1 1 0 1 1 0 0 1 0 0 1 1 0 0 0 1 1");
WillReturn.Add("0 1 1 0 1 1 0 1 0 1 0 0 1 0 0 0 0 0 1 1 0");
WillReturn.Add("1 1 0 0 1 0 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0");
WillReturn.Add("0 1 1 0 1 1 1 0 1 1 1 0 0 0 1 1 1 1 0 0 1");
WillReturn.Add("0 1 0 0 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 1 0");
WillReturn.Add("0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 1 1 1 1 1 1");
WillReturn.Add("0 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 1 1 1");
WillReturn.Add("0 0 0 0 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 0 1");
WillReturn.Add("0 1 1 0 1 1 0 0 1 1 0 0 0 1 1 1 1 0 1 1 0");
WillReturn.Add("0 0 1 0 0 1 1 1 1 0 1 1 0 1 1 1 0 0 0 0 1");
WillReturn.Add("0 1 1 0 0 1 1 1 1 0 0 0 1 0 1 1 0 1 0 1 1");
WillReturn.Add("1 1 1 1 1 0 0 0 0 1 0 0 1 1 0 1 1 1 0 0 1");
WillReturn.Add("0 0 0 1 1 0 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1");
WillReturn.Add("1 0 1 1 0 1 0 1 0 0 1 0 0 1 1 0 1 0 1 1 0");
WillReturn.Add("0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 1 1 0 0 1");
WillReturn.Add("0 0 0 1 0 0 1 1 0 1 0 1 0 1 1 0 0 1 1 0 1");
WillReturn.Add("0 0 0 0 1 1 1 0 1 0 1 1 1 0 1 1 0 0 1 1 0");
WillReturn.Add("1 1 0 1 1 0 0 1 1 0 1 1 0 1 1 1 1 1 0 1 0");
WillReturn.Add("1 0 0 1 1 0 1 1 1 1 1 0 1 0 1 1 0 0 0 0 0");
//102515160
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
const int Hou = 1000000007;
static void Main()
{
List<string> InputList = GetInputList();
int[,] BanArr = CreateBanArr(InputList.Skip(1));
int UB = BanArr.GetUpperBound(0);
int AllBitOn = (1 << (UB + 1)) - 1;
// 場合の数[マッチング済女性のBitSet] なDP表
var PrevDP = new Dictionary<int, int>();
PrevDP[0] = 1;
for (int I = 0; I <= UB; I++) {
var KouhoLadyList = new List<int>();
for (int LoopLadyInd = 0; LoopLadyInd <= UB; LoopLadyInd++) {
if (BanArr[I, LoopLadyInd] == 1) {
KouhoLadyList.Add(LoopLadyInd);
}
}
var CurrDP = new Dictionary<int, int>();
foreach (var EachPair in PrevDP) {
foreach (int EachKouhoLady in KouhoLadyList) {
int CurrBit = (1 << EachKouhoLady);
if ((EachPair.Key & CurrBit) > 0) continue;
int NewKey = EachPair.Key | CurrBit;
if (CurrDP.ContainsKey(NewKey) == false) {
CurrDP[NewKey] = 0;
}
CurrDP[NewKey] += EachPair.Value;
CurrDP[NewKey] %= Hou;
}
}
PrevDP = CurrDP;
}
if (PrevDP.ContainsKey(AllBitOn)) {
Console.WriteLine(PrevDP[AllBitOn]);
}
else {
Console.WriteLine(0);
}
}
////////////////////////////////////////////////////////////////
// IEnumerable<string>をintの2次元配列に設定する
////////////////////////////////////////////////////////////////
static int[,] CreateBanArr(IEnumerable<string> pStrEnum)
{
var StrList = pStrEnum.ToList();
if (StrList.Count == 0) {
return new int[0, 0];
}
int[] IntArr = { };
Action<string> SplitAct = pStr =>
IntArr = pStr.Split(' ').Select(pX => int.Parse(pX)).ToArray();
SplitAct(StrList[0]);
int UB_X = IntArr.GetUpperBound(0);
int UB_Y = StrList.Count - 1;
int[,] WillReturn = new int[UB_X + 1, UB_Y + 1];
for (int Y = 0; Y <= UB_Y; Y++) {
SplitAct(StrList[Y]);
for (int X = 0; X <= UB_X; X++) {
WillReturn[X, Y] = IntArr[X];
}
}
return WillReturn;
}
}