#include <iostream>
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <numeric>
#include <sstream>
#include <algorithm>
#include <functional>
#include <limits.h>
#include <bitset>

#include <tuple>
#include <unordered_map>

#define mp make_pair
#define mt make_tuple
#define pb push_back
#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int INF = 1 << 29;
const double EPS = 1e-9;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
int n, m;
ll mod;
string board[550];
ll dp[1201][1201];
int num[550];
ll memo(ll n2, ll n1) {
  if (n2 + n1 == 1) {
    return 0;
  }
  if (n2 + n1 == 0) {
    return 1;
  }
  if (dp[n2][n1] >= 0) {
    return dp[n2][n1];
  }
  ll res = 0;
  if (n2 >= 2) {
    res +=n2 * (n2 - 1) / 2 * memo(n2, n1 + 2)% mod;
  }
  if (n1 >= 2) {
    res += n1 * (n1 - 1) / 2 * memo(n2, n1 - 2)% mod;
  }
  if (n1 >= 1 and n2 >= 1) {
    res += n1 * n2 * memo(n2 - 1, n1) % mod;
  }
  return dp[n2][n1] = res;
}

int main() {
  cin >> n >> m >> mod;
  for (int i = 0; i < m; i++) {
      cin >> board[i];
      if (count(board[i].begin(), board[i].end(), '1') != 2){
        cout << 0 << endl;
        return 0;
      }
      for (int j = 0; j < n; j++){
        num[j] += board[i][j] == '1';
      }
  }
  int n2, n1;
  n2 = n1 = 0;
  for (int j = 0; j < n; j++){
    n1 += num[j] == 1;
    n2 += num[j] == 0;
  }
  memset(dp, -1, sizeof(dp));
  cout << memo(n2, n1) << endl;
  return 0;
}


#include <iostream>
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <numeric>
#include <sstream>
#include <algorithm>
#include <functional>
#include <limits.h>
#include <bitset>

#include <tuple>
#include <unordered_map>

#define mp make_pair
#define mt make_tuple
#define pb push_back
#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int INF = 1 << 29;
const double EPS = 1e-9;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
int n, m;
ll mod;
char board[550][550];
ll dp[550][550];
int cnt_col[550][550];
ll memo(int n2, int n1) {
  if (n2 + n1 == 1) {
    return 0;
  }
  if (n2 + n1 == 0) {
    return 1;
  }
  if (dp[n2][n1] >= 0) {
    return dp[n2][n1];
  }
  ll res = 0;
  if (n2 >= 2) {
    res += memo(n2 - 2, n1 + 2) % mod * n2 * (n2 - 1) / 2 % mod;
  }
  if (n1 >= 2) {
    res += memo(n2, n1 - 2) % mod * n1 * (n1 - 1) / 2 % mod;
  }
  if (n1 >= 1 and n2 >= 1) {
    res += memo(n2 - 1, n1) % mod * n1 * n2 % mod;
  }
  return dp[n2][n1] = res;
}
int main() {
  cin >> n >> m >> mod;
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
      cin >> board[i][j];
    }
  }
  for (int j = 0; j < n; j++) {
    for (int i = 0; i < m; i++) {
      if (i - 1 >= 0) {
        cnt_col[i][j] += cnt_col[i - 1][j];
      }
      if (board[i][j] == '1') {
        cnt_col[i][j]++;
      }
    }
  }
  int n2, n1;
  n2 = n1 = 0;
  for (int i = 0; i < n; i++) {
    if (cnt_col[m - 1][i] > 2) {
      cout << 0 << endl;
      return 0;
    }
    if (cnt_col[m - 1][i] == 0) {
      n2++;
    }
    if (cnt_col[m - 1][i] == 1) {
      n1++;
    }
  }
  memset(dp, -1, sizeof(dp));
  cout << memo(n2, n1) << endl;
  return 0;
}


#include <iostream>
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <numeric>
#include <sstream>
#include <algorithm>
#include <functional>
#include <limits.h>
#include <bitset>

#include <tuple>
#include <unordered_map>

#define mp make_pair
#define mt make_tuple
#define pb push_back
#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int INF = 1 << 29;
const double EPS = 1e-9;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
int n, m;
ll mod;
string board[550];
ll dp[1201][1201];
int num[550];
ll memo(ll n2, ll n1) {
  if (n2 + n1 == 1) {
    return 0;
  }
  if (n2 + n1 == 0) {
    return 1;
  }
  if (dp[n2][n1] >= 0) {
    return dp[n2][n1];
  }
  ll res = 0;
  if (n2 >= 2) {
    res += n2 * (n2 - 1) / 2 * memo(n2, n1 + 2) % mod;
  }
  if (n1 >= 2) {
    res += n1 * (n1 - 1) / 2 * memo(n2, n1 - 2) % mod;
  }
  if (n1 >= 1 and n2 >= 1) {
    res += n1 * n2 * memo(n2 - 1, n1) % mod;
  }
  return dp[n2][n1] = res;
}

int main() {
  cin >> n >> m >> mod;
  for (int i = 0; i < m; i++) {
    cin >> board[i];
    if (count(board[i].begin(), board[i].end(), '1') != 2) {
      cout << 0 << endl;
      return 0;
    }
    for (int j = 0; j < n; j++) {
      num[j] += board[i][j] == '1';
    }
  }
  int n2, n1;
  n2 = n1 = 0;
  for (int j = 0; j < n; j++) {
    n1 += num[j] == 1;
    n2 += num[j] == 0;
  }
  memset(dp, -1, sizeof(dp));
  cout << memo(n2, n1) << endl;
  return 0;
}


#include <iostream>
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <numeric>
#include <sstream>
#include <algorithm>
#include <functional>
#include <limits.h>
#include <bitset>

#include <tuple>
#include <unordered_map>

#define mp make_pair
#define mt make_tuple
#define pb push_back
#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int INF = 1 << 29;
const double EPS = 1e-9;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
int n, m;
ll mod;
char board[550][550];
ll dp[550][550];
int cnt_col[550][550];
ll memo(ll n2, ll n1) {
  if (n2 + n1 == 1) {
    return 0;
  }
  if (n2 + n1 == 0) {
    return 1;
  }
  if (dp[n2][n1] >= 0) {
    return dp[n2][n1];
  }
  ll res = 0;
  if (n2 >= 2) {
    res += memo(n2 - 2, n1 + 2) % mod * n2 * (n2 - 1) / 2 % mod;
  }
  if (n1 >= 2) {
    res += memo(n2, n1 - 2) % mod * n1 * (n1 - 1) / 2 % mod;
  }
  if (n1 >= 1 and n2 >= 1) {
    res += memo(n2 - 1, n1) % mod * n1 * n2 % mod;
  }
  return dp[n2][n1] = res;
}
int main() {
  cin >> n >> m >> mod;
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
      cin >> board[i][j];
    }
  }
  for (int j = 0; j < n; j++) {
    for (int i = 0; i < m; i++) {
      if (i - 1 >= 0) {
        cnt_col[i][j] += cnt_col[i - 1][j];
      }
      if (board[i][j] == '1') {
        cnt_col[i][j]++;
      }
    }
  }
  int n2, n1;
  n2 = n1 = 0;
  for (int i = 0; i < n; i++) {
    if (cnt_col[m - 1][i] > 2) {
      cout << 0 << endl;
      return 0;
    }
    if (cnt_col[m - 1][i] == 0) {
      n2++;
    }
    if (cnt_col[m - 1][i] == 1) {
      n1++;
    }
  }
  memset(dp, -1, sizeof(dp));
  cout << memo(n2, n1) << endl;
  return 0;
}


#include <iostream>
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <numeric>
#include <sstream>
#include <algorithm>
#include <functional>
#include <limits.h>
#include <bitset>

#include <tuple>
#include <unordered_map>

#define mp make_pair
#define mt make_tuple
#define pb push_back
#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int INF = 1 << 29;
const double EPS = 1e-9;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
int n, m;
ll mod;
string board[550];
ll dp[1201][1201];
int num[550];
ll memo(ll n2, ll n1) {
  if (n2 + n1 == 1) {
    return 0;
  }
  if (n2 + n1 == 0) {
    return 1;
  }
  if (dp[n2][n1] >= 0) {
    return dp[n2][n1];
  }
  ll res = 0;
  if (n2 >= 2) {
    res += memo(n2 - 2, n1 + 2) % mod * n2 * (n2 - 1) / 2 % mod;
  }
  if (n1 >= 2) {
    res += memo(n2, n1 - 2) % mod * n1 * (n1 - 1) / 2 % mod;
  }
  if (n1 >= 1 and n2 >= 1) {
    res += memo(n2 - 1, n1) % mod * n1 * n2 % mod;
  }
  return dp[n2][n1] = res;
}

int main() {
  cin >> n >> m >> mod;
  for (int i = 0; i < m; i++) {
      cin >> board[i];
      if (count(board[i].begin(), board[i].end(), '1') != 2){
        cout << 0 << endl;
        return 0;
      }
      for (int j = 0; j < n; j++){
        num[j] += board[i][j] == '1';
      }
  }
  int n2, n1;
  n2 = n1 = 0;
  for (int j = 0; j < n; j++){
    n1 += num[j] == 1;
    n2 += num[j] == 0;
  }
  memset(dp, -1, sizeof(dp));
  cout << memo(n2, n1) << endl;
  return 0;
}


#include <iostream>
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <numeric>
#include <sstream>
#include <algorithm>
#include <functional>
#include <limits.h>
#include <bitset>

#include <tuple>
#include <unordered_map>

#define mp make_pair
#define mt make_tuple
#define pb push_back
#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int INF = 1 << 29;
const double EPS = 1e-9;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
int n, m;
ll mod;
char board[550][550];
ll dp[550][550];
int cnt_col[550][550];
ll memo(int n2, int n1) {
  if (n2 + n1 == 1) {
    return 0;
  }
  if (n2 + n1 == 0) {
    return 1;
  }
  if (dp[n2][n1] >= 0) {
    return dp[n2][n1];
  }
  ll res = 0;
  if (n2 >= 2) {
    res += memo(n2 - 2, n1 + 2) * n2 * (n2 - 1) / 2 % mod;
  }
  if (n1 >= 2) {
    res += memo(n2, n1 - 2) * n1 * (n1 - 1) / 2 % mod;
  }
  if (n1 >= 1 and n2 >= 1){
    res += memo(n2 - 1, n1) * n1 * n2 % mod;
  }
  return dp[n2][n1] = res;
}
int main() {
  cin >> n >> m >> mod;
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
      cin >> board[i][j];
    }
  }
  for (int j = 0; j < n; j++) {
    for (int i = 0; i < m; i++) {
      if (i - 1 >= 0) {
        cnt_col[i][j] += cnt_col[i - 1][j];
      }
      if (board[i][j] == '1') {
        cnt_col[i][j]++;
      }
    }
  }
  int n2, n1;
  n2 = n1 = 0;
  for (int i = 0; i < n; i++) {
    if (cnt_col[m - 1][i] > 2) {
      cout << 0 << endl;
      return 0;
    }
    if (cnt_col[m - 1][i] == 0) {
      n2++;
    }
    if (cnt_col[m - 1][i] == 1) {
      n1++;
    }
  }
  memset(dp, -1, sizeof(dp));
  cout << memo(n2, n1) << endl;
  return 0;
}


#include <iostream>
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <numeric>
#include <sstream>
#include <algorithm>
#include <functional>
#include <limits.h>
#include <bitset>

#include <tuple>
#include <unordered_map>

#define mp make_pair
#define mt make_tuple
#define pb push_back
#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;

const int INF = 1 << 29;
const double EPS = 1e-9;

const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};
int n, m;
ll mod;
char board[550][550];
ll dp[1201][1201];
int cnt[550];
ll memo(ll n2, ll n1) {
  if (n2 + n1 == 1) {
    return 0;
  }
  if (n2 + n1 == 0) {
    return 1;
  }
  if (dp[n2][n1] >= 0) {
    return dp[n2][n1];
  }
  ll res = 0;
  if (n2 >= 2) {
    res += memo(n2 - 2, n1 + 2) % mod * n2 * (n2 - 1) / 2 % mod;
  }
  if (n1 >= 2) {
    res += memo(n2, n1 - 2) % mod * n1 * (n1 - 1) / 2 % mod;
  }
  if (n1 >= 1 and n2 >= 1) {
    res += memo(n2 - 1, n1) % mod * n1 * n2 % mod;
  }
  return dp[n2][n1] = res;
}
int main() {
  cin >> n >> m >> mod;
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < n; j++) {
      cin >> board[i][j];
    }
  }

  for (int i = 0; i < m; i++){
    for (int j = 0; j < n; j++){
        cnt[j] += board[i][j] == '1';
    }
  }
  int n2, n1;
  n2 = n1 = 0;
  for (int x = 0; x < n; x++){
    n1 += cnt[x] == 1;
    n2 += cnt[x] == 0;
  }
  memset(dp, -1, sizeof(dp));
  cout << memo(n2, n1) << endl;
  return 0;
}


#include<bits/stdc++.h>
using namespace std;

#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)

int IO;
int rd(){
	int s=0;
	while((IO=getchar())<48);
	do s=(s<<1)+(s<<3)+(IO^'0');
	while((IO=getchar())>47);
	return s;
}

const int N=510;
ll P;

int n,m;
int c[N];
ll dp[N][N];
int cnt[3];

ll dfs(int cnt1,int cnt2){
	if(cnt1==cnt[1]&&cnt[2]==cnt2) return 1;
	if(cnt1>cnt[1]||cnt2>cnt[2]) return 0;
	if(~dp[cnt1][cnt2]) return dp[cnt1][cnt2];
	ll res=(cnt1+2)*(cnt1+1)/2*dfs(cnt1+2,cnt2)%P+cnt1*(cnt2+1)*dfs(cnt1,cnt2+1)%P+(cnt2+2)*(cnt2+1)/2*dfs(cnt1-2,cnt2+2);
	return dp[cnt1][cnt2]=res%P;
}

int main(){
	n=rd(),m=rd(),P=rd();
	rep(i,1,m) rep(j,1,n) {
		int x; scanf("%1d",&x);
		c[j]+=x;
	}
	memset(dp,-1,sizeof dp);
	rep(i,1,n) cnt[2-c[i]]++;
	//dp[cnt[1]][cnt[2]]=1;
	/*drep(i,cnt[1],0) {
		drep(j,cnt[2],0) {
			if(i>=2) (dp[i-2][j]+=dp[i][j])%=P;
			if(j>=1) (dp[i][j-1]+=dp[i][j])%=P;
			(dp[i+2][j-2]+=dp[i][j])%=P;
		}
	}*/
	printf("%lld\n",dfs(0,0));
}


#include<bits/stdc++.h>
using namespace std;

#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)

int IO;
int rd(){
	int s=0;
	while((IO=getchar())<48);
	do s=(s<<1)+(s<<3)+(IO^'0');
	while((IO=getchar())>47);
	return s;
}

const int N=510;
ll P;

int n,m;
int c[N];
ll dp[N][N];
int cnt[3];

ll dfs(int cnt1,int cnt2){
	if(cnt1==cnt[1]&&cnt[2]==cnt2) return 1;
	if(cnt1>cnt[1]||cnt2>cnt[2]) return 0;
	if(cnt1<0||cnt2<0) return 0;
	if(~dp[cnt1][cnt2]) return dp[cnt1][cnt2];
	ll res=(cnt1+2)*(cnt1+1)/2*dfs(cnt1+2,cnt2)%P+cnt1*(cnt2+1)*dfs(cnt1,cnt2+1)%P+(cnt2+2)*(cnt2+1)/2*dfs(cnt1-2,cnt2+2);
	return dp[cnt1][cnt2]=res%P;
}

int main(){
	n=rd(),m=rd(),P=rd();
	rep(i,1,m) rep(j,1,n) {
		int x; scanf("%1d",&x);
		c[j]+=x;
	}
	memset(dp,-1,sizeof dp);
	rep(i,1,n) cnt[2-c[i]]++;
	//dp[cnt[1]][cnt[2]]=1;
	/*drep(i,cnt[1],0) {
		drep(j,cnt[2],0) {
			if(i>=2) (dp[i-2][j]+=dp[i][j])%=P;
			if(j>=1) (dp[i][j-1]+=dp[i][j])%=P;
			(dp[i+2][j-2]+=dp[i][j])%=P;
		}
	}*/
	printf("%lld\n",dfs(0,0));
}


#include<bits/stdc++.h>
using namespace std;

#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)

int IO;
int rd(){
	int s=0;
	while((IO=getchar())<48);
	do s=(s<<1)+(s<<3)+(IO^'0');
	while((IO=getchar())>47);
	return s;
}

const int N=510;
ll P;

int n,m;
int c[N];
ll dp[N][N];
int cnt[3];

ll dfs(int cnt1,int cnt2){
	if(cnt1==cnt[1]&&cnt[2]==cnt2) return 1;
	if(cnt1>cnt[1]||cnt2>cnt[2]) return 0;
	if(~dp[cnt1][cnt2]) return dp[cnt1][cnt2];
	ll res=dfs(cnt1+2,cnt2)+dfs(cnt1,cnt2+1)+dfs(cnt1-2,cnt2+2);
	return dp[cnt1][cnt2]=res%P;
}

int main(){
	n=rd(),m=rd(),P=rd();
	rep(i,1,m) rep(j,1,n) {
		int x; scanf("%1d",&x);
		c[j]+=x;
	}
	memset(dp,-1,sizeof dp);
	rep(i,1,n) cnt[2-c[i]]++;
	//dp[cnt[1]][cnt[2]]=1;
	/*drep(i,cnt[1],0) {
		drep(j,cnt[2],0) {
			if(i>=2) (dp[i-2][j]+=dp[i][j])%=P;
			if(j>=1) (dp[i][j-1]+=dp[i][j])%=P;
			(dp[i+2][j-2]+=dp[i][j])%=P;
		}
	}*/
	printf("%lld\n",dfs(0,0));
}


#include<bits/stdc++.h>
using namespace std;

#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)

int IO;
int rd(){
	int s=0;
	while((IO=getchar())<48);
	do s=(s<<1)+(s<<3)+(IO^'0');
	while((IO=getchar())>47);
	return s;
}

const int N=510;
ll P;

int n,m;
int c[N];
ll dp[N][N];
int cnt[3];

ll dfs(int cnt1,int cnt2){
	if(cnt1>n||cnt2>n) return 0;
	if(cnt1<0||cnt2<0) return 0;
	//cout<<cnt1<<' '<<cnt2<<endl;
	if(cnt1==cnt[1]&&cnt[2]==cnt2) return 1;
	if(~dp[cnt1][cnt2]) return dp[cnt1][cnt2];
	ll res=(cnt1+2)*(cnt1+1)/2*dfs(cnt1+2,cnt2)%P+cnt1*(cnt2+1)*dfs(cnt1,cnt2+1)%P+(cnt2+2)*(cnt2+1)/2*dfs(cnt1-2,cnt2+2);
	return dp[cnt1][cnt2]=res%P;
}

int main(){
	n=rd(),m=rd(),P=rd();
	rep(i,1,m) rep(j,1,n) {
		int x; scanf("%1d",&x);
		c[j]+=x;
	}
	memset(dp,-1,sizeof dp);
	rep(i,1,n) cnt[2-c[i]]++;
	//dp[cnt[1]][cnt[2]]=1;
	/*drep(i,cnt[1],0) {
		drep(j,cnt[2],0) {
			if(i>=2) (dp[i-2][j]+=dp[i][j])%=P;
			if(j>=1) (dp[i][j-1]+=dp[i][j])%=P;
			(dp[i+2][j-2]+=dp[i][j])%=P;
		}
	}*/
	//cout<<cnt[1]<<' '<<cnt[2]<<endl;
	printf("%lld\n",dfs(0,0));
}


#include <bits/stdc++.h>
#define MAX_N 501
#define ll long long
using namespace std;

int n, m;
ll dp[MAX_N][MAX_N][MAX_N], MOD;

ll mod(ll a) {
    if (a>=0) return (a % MOD);
    return ((a % MOD)+MOD) % MOD;
}

ll mod_add(ll a, ll b) {
    return mod(mod(a)+mod(b));
}

ll mod_mult(ll a, ll b) {
    return mod(mod(a)*mod(b));
}

ll f(int a, int b, int c) {
    if (a<0 || b<0 || c<0) return 0;
    if (dp[a][b][c]!=-1) return dp[a][b][c];
    int d=2*b-2*c+a;
    if (d<0) return 0;
    if (a==0) {
        if (d!=0) dp[a][b][c]=f(d,c,b);
        else {
            dp[a][b][c]=c*(c-1)/2;
            dp[a][b][c]=mod_mult(dp[a][b][c],f(2,c-2,c-1));
        }
        return dp[a][b][c];
    }
    ll first=mod_mult((a-1)*c,f(a-2,b,c-1)), second=mod_mult(b*c,f(a,b-1,c-1));
    dp[a][b][c]=mod_add(first,second);
    return dp[a][b][c];
}

int main(void) {
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> MOD;
    memset(dp,-1,sizeof(dp));
    int col[MAX_N];
    memset(col,0,sizeof(col));
    for (int i=0; i<m; i++) {
        string s; cin >> s;
        for (int j=0; j<n; j++) col[j]+=(s[j]=='1')? 1:0;
    }
    dp[0][1][1]=1;
    dp[1][0][0]=1;
    dp[0][0][0]=1;
    int num1=0, num2=0;
    for (int i=0; i<n; i++) {
        if (col[i]==1) num1++;
        else if (col[i]==0) num2++;
    }
    cout << f(num1, num2, n-m) << "\n";
    return 0;
}


#include <bits/stdc++.h>
#define MAX_N 510
#define ll long long
using namespace std;

int n, m;
ll dp[MAX_N][MAX_N][MAX_N], MOD;

ll mod(ll a) {
    if (a>=0) return (a % MOD);
    return ((a % MOD)+MOD) % MOD;
}

ll mod_add(ll a, ll b) {
    return mod(mod(a)+mod(b));
}

ll mod_mult(ll a, ll b) {
    return mod(mod(a)*mod(b));
}

ll f(int a, int b, int c) {
    if (a<0 || b<0 || c<0) return 0;
    if (dp[a][b][c]!=-1) return dp[a][b][c];
    int d=2*b-2*c+a;
    if (d<0) return 0;
    if (a==0) {
        if (d!=0) dp[a][b][c]=f(d,c,b);
        else {
            dp[a][b][c]=c*(c-1)/2;
            dp[a][b][c]=mod_mult(dp[a][b][c],f(2,c-2,c-1));
        }
        return dp[a][b][c];
    }
    ll first=mod_mult((a-1)*c,f(a-2,b,c-1)), second=mod_mult(b*c,f(a,b-1,c-1));
    dp[a][b][c]=mod_add(first,second);
    return dp[a][b][c];
}

int main(void) {
    ios_base::sync_with_stdio(0);
    cin >> n >> m >> MOD;
    memset(dp,-1,sizeof(dp));
    int col[MAX_N];
    memset(col,0,sizeof(col));
    for (int i=0; i<m; i++) {
        string s; cin >> s;
        for (int j=0; j<n; j++) col[j]+=(s[j]=='1')? 1:0;
    }
    dp[0][1][1]=1;
    dp[1][0][0]=1;
    dp[0][0][0]=1;
    int num1=0, num2=0;
    for (int i=0; i<n; i++) {
        if (col[i]==1) num1++;
        else if (col[i]==0) num2++;
    }
    cout << f(num1, num2, n-m) << "\n";
    return 0;
}


#include <bits/stdc++.h>
#define MAX_N 510
#define ll long long
using namespace std;

int n, m;
ll dp[MAX_N][MAX_N], MOD;

ll mod(ll a) {
    if (a>=0) return (a % MOD);
    return ((a % MOD)+MOD) % MOD;
}

ll mod_add(ll a, ll b) {
    return mod(mod(a)+mod(b));
}

ll mod_mult(ll a, ll b) {
    return mod(mod(a)*mod(b));
}

ll f(int a, int b) {
    if (dp[a][b]!=-1) return dp[a][b];
    ll ret=0;
    if (a>=2) ret=mod_add(ret,mod_mult(a*(a-1)/2,f(a-2,b)));
    if (b>=2) ret=mod_add(ret,mod_mult(b*(b-1)/2,f(a+2,b-2)));
    if (b>=1 && a>=1) ret=mod_add(ret,mod_mult(a*b,f(a,b-1)));
    dp[a][b]=ret;
    return ret;
}

int main(void) {
    cin >> n >> m >> MOD;
    memset(dp,-1,sizeof(dp));
    dp[0][0]=1;
    int col[MAX_N];
    memset(col,0,sizeof(col));
    for (int i=0; i<m; i++) {
        string s; cin >> s;
        for (int j=0; j<n; j++) col[j]+=(s[j]=='1');
    }
    int num1=0, num2=0;
    for (int i=0; i<n; i++) {
        if (col[i]==1) num1++;
        if (col[i]==0) num2++;
    }
    cout << f(num1, num2) << "\n";
    return 0;
}


#include<bits/stdc++.h>
#define M 505
#define ll long long
using namespace std;
string str[M<<1];
ll dp[M<<1][M<<1];
int n,m,P;
int cnt[M<<1],ret;
int main(){
	scanf("%d%d%d",&n,&m,&P);
	for(int i=1;i<=m;i++){
		std::cin>>str[i];
		for(int j=1;j<=n;j++){
			cnt[j]+=str[i][j-1]=='0'?0:1;
		}
	}
	for(int i=1;i<=n;i++)if(cnt[i]==1)ret++;
	dp[m][ret]=1;
	for(int i=0;i<n-m;i++){
		for(int j=0;j<=n;j+=2){
			int k=n-m-i-j/2;
			if(j&&k)dp[i+m+1][j]+=1LL*dp[i+m][j]*k%P*j%P;
			if(j>1)dp[i+m+1][j-2]+=1LL*dp[i+m][j]*j*(j-1)/2%P;
			if(k>1)dp[i+m+1][j+2]+=1LL*dp[i+m][j]*k*(k-1)/2%P;
		}
	}
	printf("%lld\n",dp[n][0]%P);
	return 0;
}


#include<bits/stdc++.h>
#define M 505
#define ll long long
using namespace std;
string str[M<<1];
ll dp[M<<1][M<<1];
int n,m,P;
int cnt[M<<1],ret;
int main(){
	scanf("%d%d%d",&n,&m,&P);
	for(int i=1;i<=m;i++){
		std::cin>>str[i];
		for(int j=1;j<=n;j++){
			cnt[j]+=str[i][j-1]=='0'?0:1;
		}
	}
	for(int i=1;i<=n;i++)if(cnt[i]==1)ret++;
	dp[m][ret]=1;
	for(int i=m;i<n;i++){
		for(int j=0;j<=n;j+=2){
			int k=n-i-j/2;
			if(j&&k)dp[i+1][j]+=1LL*dp[i][j]*k%P*j%P;
			if(j>1)dp[i+1][j-2]+=1LL*dp[i][j]*j*(j-1)/2%P;
			if(k>1)dp[i+1][j+2]+=1LL*dp[i][j]*k*(k-1)/2%P;
		}
	}
	printf("%lld\n",dp[n][0]%P);
	return 0;
}


#include <bits/stdc++.h>
#define FOR(i, a, b)    for (int i = a; i <= b; ++i)
using namespace std;
const int N = 503;
int n, m, MOD;
int dem[N], f[N][N];

void add(int &a, int b) { a = (a + b) % MOD; }

int get(int row, int zero, int one) {
    int &foo = f[zero][one];
    if (foo > -1) return foo;
    if (row == n) return zero == 0 && one == 0;

    foo = 0;
    if (zero > 1) add(foo, zero * (zero - 1)/2 * get(row + 1, zero - 2, one + 2));
    if (zero && one) add(foo, zero * one * get(row + 1, zero - 1, one));
    if (one > 1) add(foo, one * (one - 1)/2 * get(row + 1, zero, one - 2));

    return foo;
}

main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    //freopen("trash.inp","r",stdin);
    //freopen("trash.out","w",stdout);

    cin >> n >> m >> MOD;
    FOR(i, 1, m) {
        string s; cin >> s;
        FOR(j, 1, n) dem[j] += s[j - 1] == '1';
    }
    int num0 = 0, num1 = 0;
    FOR(j, 1, n) num0 += dem[j] == 0, num1 += dem[j] == 1;

    memset(f, -1, sizeof f);
    cout << get(m, num0, num1);
}


#include <bits/stdc++.h>
#define FOR(i, a, b)    for (int i = a; i <= b; ++i)
#define int             long long
using namespace std;
const int N = 503;
int n, m, MOD;
int dem[N], f[N][N];

void add(int &a, int b) { a = (a + b) % MOD; }

int get(int row, int zero, int one) {
    int &foo = f[zero][one];
    if (foo > -1) return foo;
    if (row == n) return zero == 0 && one == 0;

    foo = 0;
    if (zero > 1) add(foo, zero * (zero - 1)/2 * get(row + 1, zero - 2, one + 2));
    if (zero && one) add(foo, zero * one * get(row + 1, zero - 1, one));
    if (one > 1) add(foo, one * (one - 1)/2 * get(row + 1, zero, one - 2));

    return foo;
}

main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    //freopen("trash.inp","r",stdin);
    //freopen("trash.out","w",stdout);

    cin >> n >> m >> MOD;
    FOR(i, 1, m) {
        string s; cin >> s;
        FOR(j, 1, n) dem[j] += s[j - 1] == '1';
    }
    int num0 = 0, num1 = 0;
    FOR(j, 1, n) num0 += dem[j] == 0, num1 += dem[j] == 1;

    memset(f, -1, sizeof f);
    cout << get(m, num0, num1);
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
#include <set>
using namespace std;
#define oo 1000000007
long long int gcd(long long int a,long long int b){
      if(b==0)return a;
      return gcd(b,a%b);
}
long long int n,m,mod;
char str[505][505];
int sum[505];
long long int dp[301][301][301],no_ones,no_zero,no_thre,no_twos;

long long int rec(int zero,int ones,int left)
{

    if(dp[zero][ones][left]!=0)
        return dp[zero][ones][left];

    if (left==1 && ones==2)
    {
        return 1;
    }
    if (left==1 && zero>=1)
    {
        return 0;
    }

    long long int p1=0,p2=0,p3=0;
    if(zero>=2)
        p1=((((zero*(zero-1))/2)%mod)*rec(zero-2,ones+2,left-1))%mod;
    if(ones>=2)
        p2=(( ((ones*(ones-1))/2 )%mod)*rec(zero,ones-2,left-1))%mod;
    if(zero>=1 && ones>=1)
        p3=(((ones*(zero))%mod)*rec(zero-1,ones,left-1))%mod;
    return dp[zero][ones][left]=p1+p2+p3;
}
int main(int argc, char const *argv[])
{
        cin.sync_with_stdio(0);
        cin>>n>>m>>mod;
        dp[0][0][0]=1;
        for (int i = 0; i < m; ++i) cin>>str[i];
        no_ones=0;
        no_zero=0;
        no_twos=0;
        no_thre=0;
        for (int i = 0; i < m; ++i)
        {
            for (int j= 0; j<n; ++j)
            {
                sum[j]=sum[j]+str[i][j]-'0';
            }
        }
        for (int i = 0; i < n; ++i)
        {
            if (sum[i]==0)no_zero++;
            if (sum[i]==1)no_ones++;
            if (sum[i]==2)no_twos++;
            if (sum[i]>=3)no_thre++;
        }
        if (no_thre>=1)
        {
            cout<<"0"<<endl;
            return 0;
        }
        if(m==0)
            no_zero=n;
        cout<<rec(no_zero,no_ones,n-m)<<endl;
        return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
#include <set>
using namespace std;

long long n,m,mod;
char str[505][505];

int sum[505];
long long dp[501][501],no_ones,no_zero,no_thre,no_twos;

long long rec(int zero,int ones)
{

    if(dp[zero][ones]!=0)
        return dp[zero][ones];

    if (zero==0 && ones==2)
    {
        return 1;
    }

    if (zero==1 && ones==1)
    {
        return 0;
    }
    long long p1=0,p2=0,p3=0;
    if(zero>=2)
        p1=((((zero*(zero-1))/2)%mod)*rec(zero-2,ones+2))%mod;
    if(ones>=2)
        p2=(( ((ones*(ones-1))/2 )%mod)*rec(zero,ones-2))%mod;
    if(zero>=1 && ones>=1)
        p3=(((ones*(zero))%mod)*rec(zero-1,ones))%mod;
    return dp[zero][ones]=p1+p2+p3;
}
int main(int argc, char const *argv[])
{
        cin.sync_with_stdio(0);
        cin>>n>>m>>mod;
        dp[0][0]=1;
        for (int i = 0; i < m; ++i) cin>>str[i];
        no_ones=0;
        no_zero=0;
        no_twos=0;
        no_thre=0;
        for (int i = 0; i < m; ++i)
        {
            for (int j= 0; j<n; ++j)
            {
                sum[j]=sum[j]+str[i][j]-'0';
            }
        }
        for (int i = 0; i < n; ++i)
        {
            if (sum[i]==0)no_zero++;
            if (sum[i]==1)no_ones++;
            if (sum[i]==2)no_twos++;
            if (sum[i]>=3)no_thre++;
        }
        if (no_thre>=1)
        {
            cout<<"0"<<endl;
            return 0;
        }
        if(m==0)
            no_zero=n;
        cout<<rec(no_zero,no_ones)<<endl;
        return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
#include <set>
using namespace std;

long long n,m,mod;
char str[505][505];

int sum[505];
long long dp[501][501],no_ones,no_zero,no_thre,no_twos;

long long rec(int zero,int ones)
{

    if(dp[zero][ones]!=0)
        return dp[zero][ones];

    if (zero==0 && ones==2)
    {
        return 1;
    }

    if (zero==1 && ones==1)
    {
        return 0;
    }
    long long p1=0,p2=0,p3=0;
    if(zero>=2)
        p1=((((zero*(zero-1))/2)%mod)*rec(zero-2,ones+2))%mod;
    if(ones>=2)
        p2=(( ((ones*(ones-1))/2 )%mod)*rec(zero,ones-2))%mod;
    if(zero>=1 && ones>=1)
        p3=(((ones*(zero))%mod)*rec(zero-1,ones))%mod;
    return dp[zero][ones]=(p1+p2+p3)%mod;
}
int main(int argc, char const *argv[])
{
        cin.sync_with_stdio(0);
        cin>>n>>m>>mod;
        dp[0][0]=1;
        for (int i = 0; i < m; ++i) cin>>str[i];
        no_ones=0;
        no_zero=0;
        no_twos=0;
        no_thre=0;
        for (int i = 0; i < m; ++i)
        {
            for (int j= 0; j<n; ++j)
            {
                sum[j]=sum[j]+str[i][j]-'0';
            }
        }
        for (int i = 0; i < n; ++i)
        {
            if (sum[i]==0)no_zero++;
            if (sum[i]==1)no_ones++;
            if (sum[i]==2)no_twos++;
            if (sum[i]>=3)no_thre++;
        }
        if (no_thre>=1)
        {
            cout<<"0"<<endl;
            return 0;
        }
        if(m==0)
            no_zero=n;
        cout<<rec(no_zero,no_ones)<<endl;
        return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
#include <set>
using namespace std;

long long n,m,mod;
char str[505][505];

int sum[505];
long long dp[301][301][501],no_ones,no_zero,no_thre,no_twos;

long long rec(int zero,int ones,int left)
{

    if(dp[zero][ones][left]!=0)
        return dp[zero][ones][left];

    if (left==1 && ones==2)
    {
        return 1;
    }
    if (left==1 && zero>=1)
    {
        return 0;
    }

    long long p1=0,p2=0,p3=0;
    if(zero>=2)
        p1=((((zero*(zero-1))/2)%mod)*rec(zero-2,ones+2,left-1))%mod;
    if(ones>=2)
        p2=(( ((ones*(ones-1))/2 )%mod)*rec(zero,ones-2,left-1))%mod;
    if(zero>=1 && ones>=1)
        p3=(((ones*(zero))%mod)*rec(zero-1,ones,left-1))%mod;
    return dp[zero][ones][left]=p1+p2+p3;
}
int main(int argc, char const *argv[])
{
        cin.sync_with_stdio(0);
        cin>>n>>m>>mod;
        dp[0][0][0]=1;
        for (int i = 0; i < m; ++i) cin>>str[i];
        no_ones=0;
        no_zero=0;
        no_twos=0;
        no_thre=0;
        for (int i = 0; i < m; ++i)
        {
            for (int j= 0; j<n; ++j)
            {
                sum[j]=sum[j]+str[i][j]-'0';
            }
        }
        for (int i = 0; i < n; ++i)
        {
            if (sum[i]==0)no_zero++;
            if (sum[i]==1)no_ones++;
            if (sum[i]==2)no_twos++;
            if (sum[i]>=3)no_thre++;
        }
        if (no_thre>=1)
        {
            cout<<"0"<<endl;
            return 0;
        }
        if(m==0)
            no_zero=n;
        cout<<rec(no_zero,no_ones,n-m)<<endl;
        return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
#include <set>
using namespace std;
#define oo 1000000007
long long int gcd(long long int a,long long int b){
      if(b==0)return a;
      return gcd(b,a%b);
}
long long int n,m,mod;
char str[505][505];
int sum[505];
long long int dp[501][501][501],no_ones,no_zero,no_thre,no_twos;

long long int rec(int zero,int ones,int left)
{
    if (left==1 && ones==2)
    {
        return 1;
    }
    if (left==1 && zero>=1)
    {
        return 0;
    }
    if(dp[zero][ones][left]!=0)
        return dp[zero][ones][left];
    long long int p1=0,p2=0,p3=0;
    if(zero>=2)
        p1=(((zero*(zero-1))%mod)*rec(zero-2,ones+2,left-1))%mod;
    if(ones>=2)
        p2=(((ones*(ones-1))%mod)*rec(zero,ones-2,left-1))%mod;
    if(zero>=1 && ones>=1)
        p3=(((ones*(zero))%mod)*rec(zero-1,ones,left-1))%mod;
    return dp[zero][ones][left]=p1+p2+p3;
}
int main(int argc, char const *argv[])
{
        cin.sync_with_stdio(0);
        cin>>n>>m>>mod;

        for (int i = 0; i < m; ++i) cin>>str[i];
        no_ones=0;
        no_zero=0;
        no_twos=0;
        no_thre=0;
        for (int i = 0; i < m; ++i)
        {
            for (int j= 0; j<n; ++j)
            {
                sum[j]=sum[j]+str[i][j]-'0';
            }
        }
        for (int i = 0; i < n; ++i)
        {
            if (sum[i]==0)no_zero++;
            if (sum[i]==1)no_ones++;
            if (sum[i]==2)no_twos++;
            if (sum[i]>=3)no_thre++;
        }
        if (no_thre>=1)
        {
            cout<<"0"<<endl;
            return 0;
        }
        cout<<rec(no_zero,no_ones,n-m)<<endl;
        return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
#include <set>
using namespace std;

long long n,m,mod;
char str[505][505];

int sum[505];
long long dp[501][501],no_ones,no_zero,no_thre,no_twos;

long long rec(int zero,int ones)
{

    if(dp[zero][ones]!=0)
        return dp[zero][ones];

    if (zero==0 && ones==2)
    {
        return 1;
    }
    if (zero==2 && ones==0)
    {
        return 0;
    }
    if (zero==1 && ones==1)
    {
        return 0;
    }
    long long p1=0,p2=0,p3=0;
    if(zero>=2)
        p1=((((zero*(zero-1))/2)%mod)*rec(zero-2,ones+2))%mod;
    if(ones>=2)
        p2=(( ((ones*(ones-1))/2 )%mod)*rec(zero,ones-2))%mod;
    if(zero>=1 && ones>=1)
        p3=(((ones*(zero))%mod)*rec(zero-1,ones))%mod;
    return dp[zero][ones]=p1+p2+p3;
}
int main(int argc, char const *argv[])
{
        cin.sync_with_stdio(0);
        cin>>n>>m>>mod;
        dp[0][0]=1;
        for (int i = 0; i < m; ++i) cin>>str[i];
        no_ones=0;
        no_zero=0;
        no_twos=0;
        no_thre=0;
        for (int i = 0; i < m; ++i)
        {
            for (int j= 0; j<n; ++j)
            {
                sum[j]=sum[j]+str[i][j]-'0';
            }
        }
        for (int i = 0; i < n; ++i)
        {
            if (sum[i]==0)no_zero++;
            if (sum[i]==1)no_ones++;
            if (sum[i]==2)no_twos++;
            if (sum[i]>=3)no_thre++;
        }
        if (no_thre>=1)
        {
            cout<<"0"<<endl;
            return 0;
        }
        if(m==0)
            no_zero=n;
        cout<<rec(no_zero,no_ones)<<endl;
        return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
#include <set>
using namespace std;

long long n,m,mod;
char str[505][505];

int sum[505];
long long dp[505][505],no_ones,no_zero,no_thre,no_twos;

long long rec(int zero,int ones)
{

    if(dp[zero][ones]!=-1)
        return dp[zero][ones];

    if (zero==0 && ones==2)
    {
        return 1;
    }

    if (zero==1 && ones==1)
    {
        return 0;
    }
    long long p1=0,p2=0,p3=0;
    if(zero>=2)
        p1=((((zero*(zero-1))/2)%mod)*rec(zero-2,ones+2))%mod;
    if(ones>=2)
        p2=(( ((ones*(ones-1))/2 )%mod)*rec(zero,ones-2))%mod;
    if(zero>=1 && ones>=1)
        p3=(((ones*(zero))%mod)*rec(zero-1,ones))%mod;
    return dp[zero][ones]=(p1+p2+p3)%mod;
}
int main(int argc, char const *argv[])
{
        cin.sync_with_stdio(0);
        cin>>n>>m>>mod;
        for (int i = 0; i <=500; ++i)
        {
            for (int j= 0; j<=500; ++j)
            {
                dp[i][j]=-1;
            }
        }
        dp[0][0]=1;
        for (int i = 0; i < m; ++i) cin>>str[i];
        no_ones=0;
        no_zero=0;
        no_twos=0;
        no_thre=0;
        for (int i = 0; i < m; ++i)
        {
            for (int j= 0; j<n; ++j)
            {
                sum[j]=sum[j]+str[i][j]-'0';
            }
        }
        for (int i = 0; i < n; ++i)
        {
            if (sum[i]==0)no_zero++;
            if (sum[i]==1)no_ones++;
            if (sum[i]==2)no_twos++;
            if (sum[i]>=3)no_thre++;
        }
        if (no_thre>=1)
        {
            cout<<"0"<<endl;
            return 0;
        }
        if(m==0)
            no_zero=n;
        cout<<rec(no_zero,no_ones)<<endl;
        return 0;
}


#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
#include <set>
using namespace std;
#define oo 1000000007
long long int gcd(long long int a,long long int b){
      if(b==0)return a;
      return gcd(b,a%b);
}
long long int n,m,mod;
char str[505][505];
int sum[505];
long long int dp[301][301][301],no_ones,no_zero,no_thre,no_twos;

long long int rec(int zero,int ones,int left)
{

    if(dp[zero][ones][left]!=0)
        return dp[zero][ones][left];

    if (left==1 && ones==2)
    {
        return 1;
    }
    if (left==1 && zero>=1)
    {
        return 0;
    }

    long long int p1=0,p2=0,p3=0;
    if(zero>=2)
        p1=(((zero*(zero-1))%mod)*rec(zero-2,ones+2,left-1))%mod;
    if(ones>=2)
        p2=(((ones*(ones-1))%mod)*rec(zero,ones-2,left-1))%mod;
    if(zero>=1 && ones>=1)
        p3=(((ones*(zero))%mod)*rec(zero-1,ones,left-1))%mod;
    return dp[zero][ones][left]=p1+p2+p3;
}
int main(int argc, char const *argv[])
{
        cin.sync_with_stdio(0);
        cin>>n>>m>>mod;
        dp[0][0][0]=1;
        for (int i = 0; i < m; ++i) cin>>str[i];
        no_ones=0;
        no_zero=0;
        no_twos=0;
        no_thre=0;
        for (int i = 0; i < m; ++i)
        {
            for (int j= 0; j<n; ++j)
            {
                sum[j]=sum[j]+str[i][j]-'0';
            }
        }
        for (int i = 0; i < n; ++i)
        {
            if (sum[i]==0)no_zero++;
            if (sum[i]==1)no_ones++;
            if (sum[i]==2)no_twos++;
            if (sum[i]>=3)no_thre++;
        }
        if (no_thre>=1)
        {
            cout<<"0"<<endl;
            return 0;
        }
        cout<<rec(no_zero,no_ones,n-m)<<endl;
        return 0;
}


/*
 * if you are interested in the reference code here,
 * see https://github.com/georeth/OJLIBS for more information
 *
 * Solution Author : Georeth Chow <georeth2010@gmail.com>
 */
#include <cstdio>
#include <cmath>
#include <climits>      // INT_MIN LLONG_MIN
#include <cfloat>       // DBL_MIN DBL_MAX
#include <cstring>      // memset
#include <cstdlib>      // malloc
#include <cstdint>      // int64_t
#include <cinttypes>    // PRId64 SCNd64
#include <ctime>        // clock
#include <cassert>      // assert
#include <limits>       // numeric_limits
#include <vector>
#include <deque>
#include <map>
#include <set>
#include <tuple>        // pair, tuple
#include <iostream>     // be careful.
                        // mix with cstdio: slowwww...
                        // mix with cstdio + fastio: bug
#include <sstream>
#include <algorithm>
using namespace std;    // use as solution header. name polution is fine.
#ifdef LOCAL_JUDGE
#  define pr_debug(...) fprintf(stderr, __VA_ARGS__)
#  define pr_line() fprintf(stderr, "%s: %d\n", __FILE__, __LINE__)
#else
#  define pr_debug(...)
#  define pr_line()
#endif
template <typename T>
bool chmax(T &m, const T &v) { if (v > m) return m = v, true; return false; }
template <typename T>
bool chmin(T &m, const T &v) { if (v < m) return m = v, true; return false; }
template <typename T>
bool chinc(T &v1, T &v2) { if (v1 > v2) return swap(v1, v2), true; return false; }
template <typename T>
bool chdec(T &v1, T &v2) { if (v1 < v2) return swap(v1, v2), true; return false; }
#define ALL(x) begin(x), end(x)
#define FOR0(i,n) for(int i=0,i##end=n;i<i##end;i++)
#define FOR1(i,n) for(int i=1,i##end=n;i<=i##end;i++)
#define FOR(i,a,b) for(int i=a,i##end=b;i<=i##end;i++)
#define FOD0(i,n) for(int i=(n)-1;~i;i--)
#define FOD1(i,n) for(int i=n;i;i--)
#define FOD(i,a,b) for(int i=a,i##end=b;i>=i##end;i--)
#define FORE(i,x)for(__typeof(x.end())i=x.begin();i!=x.end();++i)
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pair<int, int>> vii;
typedef vector<vector<int>> vvi;
namespace fio {
static const char eof = '\xff';
#define LL long long
#define I inline
#define OP operator
#define RT return*this;
#define ALL_INT(mcr) mcr(int)mcr(long)mcr(LL)mcr(unsigned)mcr(unsigned long)mcr(unsigned LL)
#define ALL_FLT(mcr) mcr(float)mcr(double)mcr(long double)
#define S2D x=0;int c=P();while((c<'0'||c>'9')&&c!='-')c=P();bool h=false;if(c=='-')h=true,c=P()
#define R2D for(;c>='0'&&c<='9';c=P())x=x*10+c-'0'
#define R2F if(c=='.'){double u=0.1;for(c=P();c>='0'&&c<='9';c=P(),u*=0.1)x+=u*(c-'0');}
#define RD_INT(Int) I Fr&OP,(Int&x){S2D;R2D;if(h)x=-x;RT}
#define RD_FLT(Flt) I Fr&OP,(Flt&x){S2D;R2D;R2F;if(h)x=-x;RT}
struct Cg{I char OP()(){char c=(char)getchar();if(c == eof)valid=false;return c;};bool valid=true;};
struct Cp{I void OP()(int x){putchar(x);}};
struct Ce{I void OP()(int x){putc(x,stderr);}};
I bool IS(char x){return x==' '||x=='\r'||x=='\n'||x=='\t';}
template<class T>struct Fr{T P;ALL_INT(RD_INT)ALL_FLT(RD_FLT)I Fr&OP,(char&x){for(x=P();IS(x);)x=P();RT}
I Fr&OP,(char*s){for(*s=P();IS(*s)&&P.valid;)*s=P();for(;!IS(*s)&&P.valid;)*++s=P();*s=0;RT}
I Fr&OP,(string &s){s.clear();char c=P();for(;IS(c)&&P.valid;)c=P();for(;!IS(c)&&P.valid;)s.push_back(c),c=P();RT}
I OP bool() { return P.valid; }
};
#define W4D if(x){if(x<0)P('-'),x=-x;int p=0;while(x)B[p++]=x%10+'0',x/=10;while(p--)P(B[p]);}else P('0')
#define WR_INT(Int) I Fw&OP,(Int x){W4D;RT}
#define WR_FLT(Flt) I Fw&OP()(Flt g,int d){if(d){double t=0.5;for(int i=d;i--;)t*=0.1;if(g<0)P('-'),g=-g;g+=t;*this,(LL)(g);P('.');g-=floor(g);while(d--){g*=10;int i=(int)floor(g);P(i+'0');g-=i;}}else*this,(g>0?(LL)(g+0.5):(LL)(g-0.5));RT}
template<class T>struct Fw{T P;char B[32];ALL_INT(WR_INT)ALL_FLT(WR_FLT)I Fw&OP,(char x){P(x);RT}typedef char_traits<char>CT;typedef basic_ostream<char,CT>&OS;typedef basic_istream<char,CT>&IS;I Fw&OP,(OS&(*func)(OS)){if(func==static_cast<OS&(*)(OS)>(endl<char,CT>))P('\n');RT}I Fw&OP,(IS&(*func)(IS)){if(func==static_cast<IS&(*)(IS)>(ws<char,CT>))P(' ');RT}
I Fw&OP,(const char*s){for(;*s;++s)P(*s);RT}
I Fw&OP,(const string&s){(*this),s.c_str();RT}
template<class C>I Fw&all(const C &v, char sep=' ', char nl='\n'){auto it=v.begin();for(int i=0;i<(int)v.size();++i,++it){if(i&&sep)P(sep);(*this),*it;}if(nl)P(nl);RT}
template<class U>I Fw&print(U x){(*this),x;P('\n');RT}
template<class U,class...Us>I Fw&print(U x,Us...args){(*this),x;P(' ');print(args...);RT}
};
#undef LL
#undef I
#undef OP
#undef RT
#undef ALL_INT
#undef ALL_FLT
#undef S2D
#undef R2D
#undef R2F
#undef RD_INT
#undef RD_FLT
#undef W4D
#undef WR_INT
#undef WR_FLT
}
fio::Fr<fio::Cg>fin;
fio::Fw<fio::Cp>fout;
fio::Fw<fio::Ce>ferr;
// 	 fout.all(vec)
#include <type_traits>
#ifndef OJLIBS_USE_INT128
#  define OJLIBS_USE_INT128 1
#endif
// try binary gcd on large number
template <typename Int>
Int gcd(Int a, Int b) {
    while (a != 0) {
        b %= a;
        if (b == 0)
            return a;
        a %= b;
    }
    return b;
}
template <typename Int, typename RInt = Int>
Int lcm(Int a, Int b) {
    return a / gcd(a, b) * static_cast<RInt>(b);
}
template <typename Int, typename XInt>
Int extended_gcd(Int a, Int b, XInt &x, XInt &y) {
    static_assert(std::numeric_limits<XInt>::is_signed,
            "x, y must be signed");
    // pre condition : a != 0 || b != 0
    // post condition : a * x + b * y = g
    // (a * x) or (b * y) may overflow, but the condition
    //                 always holds.
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    /**
     * r = a - b * q
     * b * k1 + r * k2 = g
     * => a * k2 + b * (k1 - q * k2)
     *                 x = k2
     *                 y = k1 - q * k2 = k1 - q * x
     */
    Int g = extended_gcd(b, a % b, y, x);
    y -= (a / b) * x;
    return g;
}
template <typename Int>
Int mul_mod(Int a, Int b, Int m) {
    typedef int64_t TInt;
    static_assert(2 * std::numeric_limits<Int>::digits <= std::numeric_limits<TInt>::digits,
            "multiplication will overflow!");
    TInt p = a;
    p = (p * b) % m;
    return (Int)p;
}
#if defined(__SIZEOF_INT128__) && OJLIBS_USE_INT128
template <>
int64_t mul_mod<int64_t>(int64_t a, int64_t b, int64_t m) {
    __int128_t p = __int128_t(a) * b;
    return (int64_t)(p % m);
}
#else
template <>
int64_t mul_mod<int64_t>(int64_t a, int64_t b, int64_t m) {
    int64_t r = 0;
    for (int i = 63; i >= 0; --i) {
        r = (r + r) % m;
        if ((b >> i) & 1)
            r = (r + a) % m;
    }
    return r;
}
#endif
template <typename Int, typename PInt>
Int pow_mod(Int a, PInt p, Int m) {
    Int r;
    a %= m;
    for (r = 1; p; p >>= 1) {
        if (p & 1) r = mul_mod(r, a, m);
        a = mul_mod(a, a, m);
    }
    return r;
}
template <typename Int,
          typename XInt = typename std::make_signed<Int>::type>
Int inv_mod(Int a, Int m) {
    // a * x = gcd(a, m) (mod m)
    XInt x, y;
    extended_gcd(a, m, x, y);
    if (x < 0)
        return x + m;
    return x;
}
template <typename Int>
Int addx_mod(Int u, Int v, Int m) {
    Int r = u + v;
    if (r >= m) r -= m;
    return r;
}
template <typename Int>
Int subx_mod(Int u, Int v, Int m) {
    Int r = u - v;
    if (r < 0) r += m;
    return r;
}
template <typename Int>
Int div_mod(Int u, Int v, Int m) {
    // find x, s.t.
    //     u = v * x (mod m)
    // solution exist
    //     <=> gcd(v, m) | gcd(u, m)
    // g = gcd(v, m)   [do not use gcd(u, v)]
    // uu = u / g
    // vv = v / g
    // mm = m / g
    //     uu = vv * x (mod mm)
    Int g = gcd(v, m);
    assert(u % g == 0);
    Int mm = m / g;
    return mul_mod(u / g, inv_mod(v / g, mm), mm);
}
template <typename Int>
Int div_pos_r(Int a, Int b, Int &r) {
    // 3 / 2  = 1 .. 1 (ok)
    // 3 / -2 = -1 .. 1 (ok)
    // -3 / 2 = -1 .. -1 (not ok)
    // -3 / -2 = 1 .. -1 (not ok)
    // a = q b + r
    //   = (q + 1) b + (r - b)
    //   = (q - 1) b + (r + b)
    Int q = a / b;
    r = a % b;
    if (r < 0) {
        if (b < 0)
            q += 1, r -= b;
        else
            q -= 1, r += b;
    }
    return q;
}
// TODO: gauss_factorial, factorial_mod.
//       log, factorial_exp
#define INV_MOD(x)      inv_mod((x), MOD)
#define MUL_MOD(x, y)   mul_mod((x), (y), MOD)
#define MULM_MOD(x, y)  (x) = mul_mod((x), (y), MOD)
#define POW_MOD(x, y)   pow_mod((x), (y), MOD)
#define ADDX_MOD(x, y)  addx_mod((x), (y), MOD)
#define ADDM_MOD(x, y)  (x) = addx_mod((x), (y), MOD)
#define SUBX_MOD(x, y)  subx_mod((x), (y), MOD)
#define SUBM_MOD(x, y)  (x) = subx_mod((x), (y), MOD)
/* =====  SOLUTION START  ===== */
// formalize:
// dimension analysis:
static const int maxn = 505;
int n, m, MOD;
int cnt[maxn];
int dp[maxn][maxn]; // (row, nr2) -> cnt
char buf[maxn];
int C2(int n) {
    return n * (n - 1) / 2;
}
int main() {
    fin, n, m, MOD;
    FOR0(i, m) {
        fin, buf;
        FOR0(j, n) if (buf[j] == '1') ++cnt[j];
    }
    {
        int nr2 = 0;
        FOR0(i, n) {
            if (cnt[i] > 2) {
                puts("0\n");
                return 0;
            } else if (cnt[i] == 0) ++nr2;
        }
        dp[m][nr2] = 1;
    }
    FOR(i, m + 1, n) {
        FOR(nr2, 0, maxn) {
            // nr1 + 2nr2 = 2 * (n - i)
            // (in the last row)
            int nr1 = 2 * (n - i + 1) - 2 * nr2;
            if (nr1 >= 2) ADDM_MOD(dp[i][nr2],
                    MUL_MOD(dp[i - 1][nr2], C2(nr1)));
            if (nr2 >= 2) ADDM_MOD(dp[i][nr2],
                    MUL_MOD(dp[i - 1][nr2 - 2], C2(nr2)));
            if (nr1 >= 1 && nr2 >= 1) ADDM_MOD(dp[i][nr2 - 1],
                    MUL_MOD(dp[i - 1][nr2], MUL_MOD(nr1, nr2)));
        }
    }
    fout, dp[n][0], endl;
    return 0;
}


/*
 * if you are interested in the reference code here,
 * see https://github.com/georeth/OJLIBS for more information
 *
 * Solution Author : Georeth Chow <georeth2010@gmail.com>
 */
#include <cstdio>
#include <cmath>
#include <cstring>      // memset
#include <cstdlib>      // malloc
#include <cstdint>      // int64_t
#include <cinttypes>    // PRId64 SCNd64
#include <cassert>      // assert
#include <limits>       // numeric_limits
#include <vector>
#include <deque>
#include <map>
#include <set>
#include <tuple>        // pair, tuple
#include <iostream>     // be careful
#include <sstream>
#include <algorithm>
#include <utility>
#include <iterator>
template <typename It>
struct iter_range : std::pair<It, It> {
    typedef std::pair<It, It> base_t;
    typedef It iterator;
    using base_t::base_t;
    It begin() { return base_t::first; }
    It end() { return base_t::second; }
};
template <typename It>
iter_range<std::reverse_iterator<It>> rev(const iter_range<It> &origin) {
    using rev_t = std::reverse_iterator<It>;
    return {rev_t(origin.second), rev_t(origin.first)};
}
// TODO: rev on std::string, etc.
template <typename Int = int>
struct int_iter {
    Int i;
    explicit int_iter(Int i = 0) : i(i) { }
    Int operator*() const { return i; }
    int_iter &operator++() { ++i; return *this; }
    int_iter &operator--() { --i; return *this; }
    int_iter operator+(Int step) const { return int_iter(i + step); }
    int_iter operator-(Int step) const { return int_iter(i - step); }
    Int operator-(const int_iter &that) const { return i - that.i; }
    int_iter &operator+=(Int step) { i += step; return *this; }
    int_iter &operator-=(Int step) { i -= step; return *this; }
    bool operator==(const int_iter &that) const { return  i == that.i; }
    bool operator!=(const int_iter &that) const { return !(*this == that); }
    Int operator[](Int n) { return i + n; }
    typedef Int difference_type;
    typedef Int value_type;
    typedef Int *pointer;
    typedef Int reference; // not a int container, never reference to int
    typedef std::random_access_iterator_tag iterator_category;
};
template <typename Int = int>
using int_range = iter_range<int_iter<Int>>;
template <typename Int>
int_range<Int> range(Int b, Int e) { return {int_iter<Int>(b), int_iter<Int>(e > b ? e : b)}; }
template <typename Int>
int_range<Int> range(Int n) { return range(Int(), n); }
template <typename Int>
int_range<Int> nrange(Int n) { return range(Int(1), Int(n+1)); }
template <typename Int>
int_range<Int> inrange(Int b, Int e) { return range(b, Int(e + 1)); }
using namespace std;    // use as solution header. name polution is fine.
#ifdef LOCAL_JUDGE
#  define pr_debug(...) fprintf(stderr, __VA_ARGS__)
#  define pr_line() fprintf(stderr, "%s: %d\n", __FILE__, __LINE__)
#else
#  define pr_debug(...)
#  define pr_line()
#endif
template <typename T>
bool chmax(T &m, const T &v) { if (v > m) return m = v, true; return false; }
template <typename T>
bool chmin(T &m, const T &v) { if (v < m) return m = v, true; return false; }
template <typename T>
T max_s(const T &v) { return v; }
template <typename T, typename... Args>
T max_s(const T &v1, const T &v2, Args... arg) {
    return max_s(max(v1, v2), arg...);
}
template <typename T>
T min_s(const T &v) { return v; }
template <typename T, typename... Args>
T min_s(const T &v1, const T &v2, Args... arg) {
    return min_s(min(v1, v2), arg...);
}
static const int HMAX32 = INT32_MAX / 2;
static const int64_t HMAX64 = INT64_MAX / 2;
#define fast_io\
    ios_base::sync_with_stdio(false); cin.tie(nullptr)
stringstream line_stream() {
    string str;
    getline(cin, str);
    return stringstream(str);
}
#define read_int(id) scanf("%d", &id)
#define read_int64(id) scanf("%" PRId64, &id)
#define new_int(id) int id; read_int(id)
#define new_int64(id) int64_t id; read_int64(id)
#define ALL(x) begin(x), end(x)
#include <type_traits>
// Suggested Reading : (GTM 138 by Henri Cohen) A course in computational algebraic number theory
//
// TODO : use gcc arith extension like __builtin_add_overflow
// try binary gcd on large number
template <typename Int>
Int gcd(Int a, Int b) {
    while (a != 0) {
        b %= a;
        if (b == 0)
            return a;
        a %= b;
    }
    return b;
}
template <typename Int, typename RInt = Int>
Int lcm(Int a, Int b) {
    return a / gcd(a, b) * static_cast<RInt>(b);
}
template <typename Int, typename XInt>
Int extended_gcd(Int a, Int b, XInt &x, XInt &y) {
    static_assert(std::numeric_limits<XInt>::is_signed,
            "x, y must be signed");
    // pre condition : a != 0 || b != 0
    // post condition : a * x + b * y = g
    // (a * x) or (b * y) may overflow, but the condition
    //                 always holds.
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    /**
     * r = a - b * q
     * b * k1 + r * k2 = g
     * => a * k2 + b * (k1 - q * k2)
     *                 x = k2
     *                 y = k1 - q * k2 = k1 - q * x
     */
    Int g = extended_gcd(b, a % b, y, x);
    y -= (a / b) * x;
    return g;
}
template <typename Int, typename TInt = int64_t>
Int mul_mod(Int a, Int b, Int m) {
    TInt p = a;
    p = (p * b) % m;
    return (Int)p;
}
template <typename Int, typename PInt, typename TInt = int64_t>
Int pow_mod(Int a, PInt p, Int m) {
    Int r;
    a %= m;
    for (r = 1; p; p >>= 1) {
        if (p & 1) r = mul_mod(r, a, m);
        a = mul_mod(a, a, m);
    }
    return r;
}
template <typename Int,
          typename XInt = typename std::make_signed<Int>::type>
Int inv_mod(Int a, Int m) {
    // a * x = gcd(a, m) (mod m)
    XInt x, y;
    extended_gcd(a, m, x, y);
    if (x < 0)
        return x + m;
    return x;
}
template <typename Int>
static Int addx_mod(Int u, Int v, Int m) {
    Int r = u + v;
    if (r >= m) r -= m;
    return r;
}
template <typename Int>
static Int subx_mod(Int u, Int v, Int m) {
    Int r = u - v;
    if (r < 0) r += m;
    return r;
}
template <typename Int>
Int div_pos_r(Int a, Int b, Int &r) {
    // 3 / 2  = 1 .. 1 (ok)
    // 3 / -2 = -1 .. 1 (ok)
    // -3 / 2 = -1 .. -1 (not ok)
    // -3 / -2 = 1 .. -1 (not ok)
    // a = q b + r
    //   = (q + 1) b + (r - b)
    //   = (q - 1) b + (r + b)
    Int q = a / b;
    r = a % b;
    if (r < 0) {
        if (b < 0)
            q += 1, r -= b;
        else
            q -= 1, r += b;
    }
    return q;
}
template <typename Int, typename TInt = int64_t>
TInt crt2(Int a1, Int m1, Int a2, Int m2) {
    // Pre condition: consistency
    //                 for every (i, j)
    //                 ai = aj (mod gcd(mi, mj))
    // Post condition:
    //         x = a1 (mod m1)
    //         x = a2 (mod m2)
    //  |x| < m1 * m2
    //
    //  x >= 0 may not hold!!
    Int k1, k2;
    Int g = extended_gcd(m1, m2, k1, k2);
    Int r1, r2;
    a1 = div_pos_r(a1, g, r1);
    a2 = div_pos_r(a2, g, r2);
    if (r1 != r2)
        throw 0;
    m1 /= g; m2 /= g; // no remainder
    TInt m12 = static_cast<TInt>(m1) * m2;
    // m1 * k1 + m2 * k2 = 1
    // a2 * m1 * k1 + a1 * m2 * k2
    //   = a1 + (a2 - a1) * m1 * k1 = a1 (mod m1)
    //   = a2 + (a1 - a2) * m2 * k2 = a2 (mod m2)
    return (static_cast<TInt>(a2) * k1 % m2 * m1 +
            static_cast<TInt>(a1) * k2 % m1 * m2) % m12 * g + r1;
}
template <typename Int>
Int counting(Int L, Int R, Int x0, Int dx) {
    // return number of d, s.t.
    //          L <= x0 + d * dx <= R
    Int tmp;
    return div_pos_r(R - x0, dx, tmp) - div_pos_r(L - 1 - x0, dx, tmp);
}
template <typename Int, typename TInt = int64_t>
TInt crtn(const std::vector<Int> &as, const std::vector<Int> &ms) {
    // Pre condition:
    //          pairwise coprime
    TInt r = 1;
    TInt m = 1;
    for (int i = 0; i < as.size(); ++i) {
        r = crt2<TInt, TInt>(r, m, as[i], ms[i]);
        m *= ms[i];
    }
    return r;
}
// TODO :gauss_factorial, factorial_mod.
template <typename Int>
Int factorial_exp(Int n, Int p) {
    Int r = 0;
    while (n) {
        n = n / p;
        r += n;
    }
    return r;
}
template <typename Int>
std::pair<Int, bool> log(Int n, Int b) {
    // log = 3.3
    // return (3, true)
    if (n <= 0)
        return {-1, true};
    Int ans = 0;
    bool frac = false;
    while (n >= b) {
        frac = frac || (n % b != 0);
        ans += 1;
        n /= b;
    }
    if (n != 1) frac = true;
    return {ans, frac};
}
#define INV_MOD(x)      inv_mod((x), MOD)
#define MUL_MOD(x, y)   mul_mod((x), (y), MOD)
#define MULM_MOD(x, y)  (x) = mul_mod((x), (y), MOD)
#define POW_MOD(x, y)   pow_mod((x), (y), MOD)
#define ADDX_MOD(x, y)  addx_mod((x), (y), MOD)
#define ADDM_MOD(x, y)  (x) = addx_mod((x), (y), MOD)
#define SUBX_MOD(x, y)  subx_mod((x), (y), MOD)
#define SUBM_MOD(x, y)  (x) = subx_mod((x), (y), MOD)
// warning : mod is PRIME enough PRIME
struct factorial_list {
    std::vector<int> fact;
    int mod;
    factorial_list(int n, int mod) : fact(n + 1), mod(mod) {
        fact[0] = 1;
        for (int i = 1; i <= n; ++i)
            fact[i] = mul_mod(fact[i - 1], i, mod);
    }
    int operator()(int n) { return fact[n]; }
    int A(int n, int m) {
        return mul_mod(fact[n], inv_mod(fact[n - m], mod), mod);
    }
    int C(int n, int m) {
        if (m > n || n < 0 || m < 0) return 0;
        return mul_mod(A(n, m), inv_mod(fact[m], mod), mod);
    }
    int H(int n, int m) {
        return C(n + m - 1, m);
    }
};
// C(n, m) = C(n, n - m)
// Be cautious about overflow
/* =====  SOLUTION START  ===== */
// incident matrix of cycles (length >= 2)
// length 2 is special (two same lines in matrix)
//
//
// second attack: count sum of each column
//      dp[k][x][y] = on line k, "0" * x, "1" * 2y
//      rolling on k
// third attack:
//      "0" * x, "1" * y, "2" * z
//      y + 2z = 2k
//      x + y + z = n
//      only one free var x
//      y = 2n - 2x - 2k
//      z = 2k - n + x
int dp[505][505]; // k, x
char str[1005];
int sum[505];
int main() {
    new_int(n);
    new_int(m);
    new_int(MOD);
    vector<int> deg(n);
    for (int i : range(m)) {
        scanf("%s", str);
        for (int j : range(n))
            if (str[j] == '1') ++sum[j];
    }
    int nr_0 = 0;
    int nr_1 = 0;
    for (int j : range(n)) {
        if (sum[j] == 0) ++nr_0;
        if (sum[j] == 1) ++nr_1;
    }
    dp[m][nr_0] = 1;
    for (int k : range(m, n)) {
        pr_debug("#%d\n", k);
        for (int x : inrange(0, n)) {
            int y = 2 * n - 2 * x - 2 * k;
            int z = 2 * k - n + x;
            if (y < 0 || z < 0) continue;
            pr_debug("x y z = %d %d %d = %d\n", x, y, z, dp[k][x]);
            // xyz
            // 0, 0 -> 1, 1
            if (x >= 2) ADDM_MOD(dp[k + 1][x - 2], MUL_MOD(dp[k][x], x * (x - 1) / 2));
            // 0, 1 -> 1, 2
            if (x >= 1 && y >= 1) ADDM_MOD(dp[k + 1][x - 1], MUL_MOD(dp[k][x], MUL_MOD(x, y)));
            // 1, 1 -> 2, 2
            if (y >= 2) ADDM_MOD(dp[k + 1][x], MUL_MOD(dp[k][x], y * (y - 1) / 2));
        }
    }
    int ans = dp[n][0];
    printf("%d\n", ans);
    return 0;
}


/*
 * if you are interested in the reference code here,
 * see https://github.com/georeth/OJLIBS for more information
 *
 * Solution Author : Georeth Chow <georeth2010@gmail.com>
 */
#include <cstdio>
#include <cmath>
#include <climits>      // INT_MIN LLONG_MIN
#include <cfloat>       // DBL_MIN DBL_MAX
#include <cstring>      // memset
#include <cstdlib>      // malloc
#include <cstdint>      // int64_t
#include <cinttypes>    // PRId64 SCNd64
#include <ctime>        // clock
#include <cassert>      // assert
#include <limits>       // numeric_limits
#include <vector>
#include <deque>
#include <map>
#include <set>
#include <tuple>        // pair, tuple
#include <iostream>     // be careful.
                        // mix with cstdio: slowwww...
                        // mix with cstdio + fastio: bug
#include <sstream>
#include <algorithm>
using namespace std;    // use as solution header. name polution is fine.
#ifdef LOCAL_JUDGE
#  define pr_debug(...) fprintf(stderr, __VA_ARGS__)
#  define pr_line() fprintf(stderr, "%s: %d\n", __FILE__, __LINE__)
#else
#  define pr_debug(...)
#  define pr_line()
#endif
template <typename T>
bool chmax(T &m, const T &v) { if (v > m) return m = v, true; return false; }
template <typename T>
bool chmin(T &m, const T &v) { if (v < m) return m = v, true; return false; }
template <typename T>
bool chinc(T &v1, T &v2) { if (v1 > v2) return swap(v1, v2), true; return false; }
template <typename T>
bool chdec(T &v1, T &v2) { if (v1 < v2) return swap(v1, v2), true; return false; }
#define ALL(x) begin(x), end(x)
#define FOR0(i,n) for(int i=0,i##end=n;i<i##end;i++)
#define FOR1(i,n) for(int i=1,i##end=n;i<=i##end;i++)
#define FOR(i,a,b) for(int i=a,i##end=b;i<=i##end;i++)
#define FOD0(i,n) for(int i=(n)-1;~i;i--)
#define FOD1(i,n) for(int i=n;i;i--)
#define FOD(i,a,b) for(int i=a,i##end=b;i>=i##end;i--)
#define FORE(i,x)for(__typeof(x.end())i=x.begin();i!=x.end();++i)
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pair<int, int>> vii;
typedef vector<vector<int>> vvi;
namespace fio {
static const char eof = '\xff';
#define LL long long
#define I inline
#define OP operator
#define RT return*this;
#define ALL_INT(mcr) mcr(int)mcr(long)mcr(LL)mcr(unsigned)mcr(unsigned long)mcr(unsigned LL)
#define ALL_FLT(mcr) mcr(float)mcr(double)mcr(long double)
#define S2D x=0;int c=P();while((c<'0'||c>'9')&&c!='-')c=P();bool h=false;if(c=='-')h=true,c=P()
#define R2D for(;c>='0'&&c<='9';c=P())x=x*10+c-'0'
#define R2F if(c=='.'){double u=0.1;for(c=P();c>='0'&&c<='9';c=P(),u*=0.1)x+=u*(c-'0');}
#define RD_INT(Int) I Fr&OP,(Int&x){S2D;R2D;if(h)x=-x;RT}
#define RD_FLT(Flt) I Fr&OP,(Flt&x){S2D;R2D;R2F;if(h)x=-x;RT}
struct Cg{I char OP()(){char c=(char)getchar();if(c == eof)valid=false;return c;};bool valid=true;};
struct Cp{I void OP()(int x){putchar(x);}};
struct Ce{I void OP()(int x){putc(x,stderr);}};
I bool IS(char x){return x==' '||x=='\r'||x=='\n'||x=='\t';}
template<class T>struct Fr{T P;ALL_INT(RD_INT)ALL_FLT(RD_FLT)I Fr&OP,(char&x){for(x=P();IS(x);)x=P();RT}
I Fr&OP,(char*s){for(*s=P();IS(*s)&&P.valid;)*s=P();for(;!IS(*s)&&P.valid;)*++s=P();*s=0;RT}
I Fr&OP,(string &s){s.clear();char c=P();for(;IS(c)&&P.valid;)c=P();for(;!IS(c)&&P.valid;)s.push_back(c),c=P();RT}
I OP bool() { return P.valid; }
};
#define W4D if(x){if(x<0)P('-'),x=-x;int p=0;while(x)B[p++]=x%10+'0',x/=10;while(p--)P(B[p]);}else P('0')
#define WR_INT(Int) I Fw&OP,(Int x){W4D;RT}
#define WR_FLT(Flt) I Fw&OP()(Flt g,int d){if(d){double t=0.5;for(int i=d;i--;)t*=0.1;if(g<0)P('-'),g=-g;g+=t;*this,(LL)(g);P('.');g-=floor(g);while(d--){g*=10;int i=(int)floor(g);P(i+'0');g-=i;}}else*this,(g>0?(LL)(g+0.5):(LL)(g-0.5));RT}
template<class T>struct Fw{T P;char B[32];ALL_INT(WR_INT)ALL_FLT(WR_FLT)I Fw&OP,(char x){P(x);RT}typedef char_traits<char>CT;typedef basic_ostream<char,CT>&OS;typedef basic_istream<char,CT>&IS;I Fw&OP,(OS&(*func)(OS)){if(func==static_cast<OS&(*)(OS)>(endl<char,CT>))P('\n');RT}I Fw&OP,(IS&(*func)(IS)){if(func==static_cast<IS&(*)(IS)>(ws<char,CT>))P(' ');RT}
I Fw&OP,(const char*s){for(;*s;++s)P(*s);RT}
I Fw&OP,(const string&s){(*this),s.c_str();RT}
template<class C>I Fw&all(const C &v, char sep=' ', char nl='\n'){auto it=v.begin();for(int i=0;i<(int)v.size();++i,++it){if(i&&sep)P(sep);(*this),*it;}if(nl)P(nl);RT}
template<class U>I Fw&print(U x){(*this),x;P('\n');RT}
template<class U,class...Us>I Fw&print(U x,Us...args){(*this),x;P(' ');print(args...);RT}
};
#undef LL
#undef I
#undef OP
#undef RT
#undef ALL_INT
#undef ALL_FLT
#undef S2D
#undef R2D
#undef R2F
#undef RD_INT
#undef RD_FLT
#undef W4D
#undef WR_INT
#undef WR_FLT
}
fio::Fr<fio::Cg>fin;
fio::Fw<fio::Cp>fout;
fio::Fw<fio::Ce>ferr;
// 	 fout.all(vec)
#include <type_traits>
#ifndef OJLIBS_USE_INT128
#  define OJLIBS_USE_INT128 1
#endif
// try binary gcd on large number
template <typename Int>
Int gcd(Int a, Int b) {
    while (a != 0) {
        b %= a;
        if (b == 0)
            return a;
        a %= b;
    }
    return b;
}
template <typename Int, typename RInt = Int>
Int lcm(Int a, Int b) {
    return a / gcd(a, b) * static_cast<RInt>(b);
}
template <typename Int, typename XInt>
Int extended_gcd(Int a, Int b, XInt &x, XInt &y) {
    static_assert(std::numeric_limits<XInt>::is_signed,
            "x, y must be signed");
    // pre condition : a != 0 || b != 0
    // post condition : a * x + b * y = g
    // (a * x) or (b * y) may overflow, but the condition
    //                 always holds.
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    /**
     * r = a - b * q
     * b * k1 + r * k2 = g
     * => a * k2 + b * (k1 - q * k2)
     *                 x = k2
     *                 y = k1 - q * k2 = k1 - q * x
     */
    Int g = extended_gcd(b, a % b, y, x);
    y -= (a / b) * x;
    return g;
}
template <typename Int>
Int mul_mod(Int a, Int b, Int m) {
    typedef int64_t TInt;
    static_assert(2 * std::numeric_limits<Int>::digits <= std::numeric_limits<TInt>::digits,
            "multiplication will overflow!");
    TInt p = a;
    p = (p * b) % m;
    return (Int)p;
}
#if defined(__SIZEOF_INT128__) && OJLIBS_USE_INT128
template <>
int64_t mul_mod<int64_t>(int64_t a, int64_t b, int64_t m) {
    __int128_t p = __int128_t(a) * b;
    return (int64_t)(p % m);
}
#else
template <>
int64_t mul_mod<int64_t>(int64_t a, int64_t b, int64_t m) {
    int64_t r = 0;
    for (int i = 63; i >= 0; --i) {
        r = (r + r) % m;
        if ((b >> i) & 1)
            r = (r + a) % m;
    }
    return r;
}
#endif
template <typename Int, typename PInt>
Int pow_mod(Int a, PInt p, Int m) {
    Int r;
    a %= m;
    for (r = 1; p; p >>= 1) {
        if (p & 1) r = mul_mod(r, a, m);
        a = mul_mod(a, a, m);
    }
    return r;
}
template <typename Int,
          typename XInt = typename std::make_signed<Int>::type>
Int inv_mod(Int a, Int m) {
    // a * x = gcd(a, m) (mod m)
    XInt x, y;
    extended_gcd(a, m, x, y);
    if (x < 0)
        return x + m;
    return x;
}
template <typename Int>
Int addx_mod(Int u, Int v, Int m) {
    Int r = u + v;
    if (r >= m) r -= m;
    return r;
}
template <typename Int>
Int subx_mod(Int u, Int v, Int m) {
    Int r = u - v;
    if (r < 0) r += m;
    return r;
}
template <typename Int>
Int div_mod(Int u, Int v, Int m) {
    // find x, s.t.
    //     u = v * x (mod m)
    // solution exist
    //     <=> gcd(v, m) | gcd(u, m)
    // g = gcd(v, m)   [do not use gcd(u, v)]
    // uu = u / g
    // vv = v / g
    // mm = m / g
    //     uu = vv * x (mod mm)
    Int g = gcd(v, m);
    assert(u % g == 0);
    Int mm = m / g;
    return mul_mod(u / g, inv_mod(v / g, mm), mm);
}
template <typename Int>
Int div_pos_r(Int a, Int b, Int &r) {
    // 3 / 2  = 1 .. 1 (ok)
    // 3 / -2 = -1 .. 1 (ok)
    // -3 / 2 = -1 .. -1 (not ok)
    // -3 / -2 = 1 .. -1 (not ok)
    // a = q b + r
    //   = (q + 1) b + (r - b)
    //   = (q - 1) b + (r + b)
    Int q = a / b;
    r = a % b;
    if (r < 0) {
        if (b < 0)
            q += 1, r -= b;
        else
            q -= 1, r += b;
    }
    return q;
}
// TODO: gauss_factorial, factorial_mod.
//       log, factorial_exp
#define INV_MOD(x)      inv_mod((x), MOD)
#define MUL_MOD(x, y)   mul_mod((x), (y), MOD)
#define MULM_MOD(x, y)  (x) = mul_mod((x), (y), MOD)
#define POW_MOD(x, y)   pow_mod((x), (y), MOD)
#define ADDX_MOD(x, y)  addx_mod((x), (y), MOD)
#define ADDM_MOD(x, y)  (x) = addx_mod((x), (y), MOD)
#define SUBX_MOD(x, y)  subx_mod((x), (y), MOD)
#define SUBM_MOD(x, y)  (x) = subx_mod((x), (y), MOD)
/* =====  SOLUTION START  ===== */
// formalize:
// dimension analysis:
static const int maxn = 505;
int n, m, MOD;
int cnt[maxn];
int dp[maxn][maxn]; // (row, nr2) -> cnt
char buf[maxn];
int C2(int n) {
    return n * (n - 1) / 2;
}
int main() {
    fin, n, m, MOD;
    FOR0(i, m) {
        fin, buf;
        FOR0(j, n) if (buf[j] == '1') ++cnt[j];
    }
    {
        int nr2 = 0;
        FOR0(i, n) {
            if (cnt[i] > 2) {
                puts("0\n");
                return 0;
            } else if (cnt[i] == 0) ++nr2;
        }
        dp[m][nr2] = 1;
    }
    FOR(i, m + 1, n) {
        FOR(nr2, 0, maxn) {
            // nr1 + 2nr2 = 2 * (n - i)
            // (in the last row)
            int nr1 = 2 * (n - i + 1) - 2 * nr2;
            if (nr1 >= 2) ADDM_MOD(dp[i][nr2],
                    MUL_MOD(dp[i - 1][nr2], C2(nr1)));
            if (nr1 >= 1 && nr2 >= 1) ADDM_MOD(dp[i][nr2 - 1],
                    MUL_MOD(dp[i - 1][nr2], MUL_MOD(nr1, nr2)));
        }
    }
    fout, dp[n][0], endl;
    return 0;
}


/*
 * if you are interested in the reference code here,
 * see https://github.com/georeth/OJLIBS for more information
 *
 * Solution Author : Georeth Chow <georeth2010@gmail.com>
 */
#include <cstdio>
#include <cmath>
#include <climits>      // INT_MIN LLONG_MIN
#include <cfloat>       // DBL_MIN DBL_MAX
#include <cstring>      // memset
#include <cstdlib>      // malloc
#include <cstdint>      // int64_t
#include <cinttypes>    // PRId64 SCNd64
#include <ctime>        // clock
#include <cassert>      // assert
#include <limits>       // numeric_limits
#include <vector>
#include <deque>
#include <map>
#include <set>
#include <tuple>        // pair, tuple
#include <iostream>     // be careful.
                        // mix with cstdio: slowwww...
                        // mix with cstdio + fastio: bug
#include <sstream>
#include <algorithm>
using namespace std;    // use as solution header. name polution is fine.
#ifdef LOCAL_JUDGE
#  define pr_debug(...) fprintf(stderr, __VA_ARGS__)
#  define pr_line() fprintf(stderr, "%s: %d\n", __FILE__, __LINE__)
#else
#  define pr_debug(...)
#  define pr_line()
#endif
template <typename T>
bool chmax(T &m, const T &v) { if (v > m) return m = v, true; return false; }
template <typename T>
bool chmin(T &m, const T &v) { if (v < m) return m = v, true; return false; }
template <typename T>
bool chinc(T &v1, T &v2) { if (v1 > v2) return swap(v1, v2), true; return false; }
template <typename T>
bool chdec(T &v1, T &v2) { if (v1 < v2) return swap(v1, v2), true; return false; }
#define ALL(x) begin(x), end(x)
#define FOR0(i,n) for(int i=0,i##end=n;i<i##end;i++)
#define FOR1(i,n) for(int i=1,i##end=n;i<=i##end;i++)
#define FOR(i,a,b) for(int i=a,i##end=b;i<=i##end;i++)
#define FOD0(i,n) for(int i=(n)-1;~i;i--)
#define FOD1(i,n) for(int i=n;i;i--)
#define FOD(i,a,b) for(int i=a,i##end=b;i>=i##end;i--)
#define FORE(i,x)for(__typeof(x.end())i=x.begin();i!=x.end();++i)
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pair<int, int>> vii;
typedef vector<vector<int>> vvi;
namespace fio {
static const char eof = '\xff';
#define LL long long
#define I inline
#define OP operator
#define RT return*this;
#define ALL_INT(mcr) mcr(int)mcr(long)mcr(LL)mcr(unsigned)mcr(unsigned long)mcr(unsigned LL)
#define ALL_FLT(mcr) mcr(float)mcr(double)mcr(long double)
#define S2D x=0;int c=P();while((c<'0'||c>'9')&&c!='-')c=P();bool h=false;if(c=='-')h=true,c=P()
#define R2D for(;c>='0'&&c<='9';c=P())x=x*10+c-'0'
#define R2F if(c=='.'){double u=0.1;for(c=P();c>='0'&&c<='9';c=P(),u*=0.1)x+=u*(c-'0');}
#define RD_INT(Int) I Fr&OP,(Int&x){S2D;R2D;if(h)x=-x;RT}
#define RD_FLT(Flt) I Fr&OP,(Flt&x){S2D;R2D;R2F;if(h)x=-x;RT}
struct Cg{I char OP()(){char c=(char)getchar();if(c == eof)valid=false;return c;};bool valid=true;};
struct Cp{I void OP()(int x){putchar(x);}};
struct Ce{I void OP()(int x){putc(x,stderr);}};
I bool IS(char x){return x==' '||x=='\r'||x=='\n'||x=='\t';}
template<class T>struct Fr{T P;ALL_INT(RD_INT)ALL_FLT(RD_FLT)I Fr&OP,(char&x){for(x=P();IS(x);)x=P();RT}
I Fr&OP,(char*s){for(*s=P();IS(*s)&&P.valid;)*s=P();for(;!IS(*s)&&P.valid;)*++s=P();*s=0;RT}
I Fr&OP,(string &s){s.clear();char c=P();for(;IS(c)&&P.valid;)c=P();for(;!IS(c)&&P.valid;)s.push_back(c),c=P();RT}
I OP bool() { return P.valid; }
};
#define W4D if(x){if(x<0)P('-'),x=-x;int p=0;while(x)B[p++]=x%10+'0',x/=10;while(p--)P(B[p]);}else P('0')
#define WR_INT(Int) I Fw&OP,(Int x){W4D;RT}
#define WR_FLT(Flt) I Fw&OP()(Flt g,int d){if(d){double t=0.5;for(int i=d;i--;)t*=0.1;if(g<0)P('-'),g=-g;g+=t;*this,(LL)(g);P('.');g-=floor(g);while(d--){g*=10;int i=(int)floor(g);P(i+'0');g-=i;}}else*this,(g>0?(LL)(g+0.5):(LL)(g-0.5));RT}
template<class T>struct Fw{T P;char B[32];ALL_INT(WR_INT)ALL_FLT(WR_FLT)I Fw&OP,(char x){P(x);RT}typedef char_traits<char>CT;typedef basic_ostream<char,CT>&OS;typedef basic_istream<char,CT>&IS;I Fw&OP,(OS&(*func)(OS)){if(func==static_cast<OS&(*)(OS)>(endl<char,CT>))P('\n');RT}I Fw&OP,(IS&(*func)(IS)){if(func==static_cast<IS&(*)(IS)>(ws<char,CT>))P(' ');RT}
I Fw&OP,(const char*s){for(;*s;++s)P(*s);RT}
I Fw&OP,(const string&s){(*this),s.c_str();RT}
template<class C>I Fw&all(const C &v, char sep=' ', char nl='\n'){auto it=v.begin();for(int i=0;i<(int)v.size();++i,++it){if(i&&sep)P(sep);(*this),*it;}if(nl)P(nl);RT}
template<class U>I Fw&print(U x){(*this),x;P('\n');RT}
template<class U,class...Us>I Fw&print(U x,Us...args){(*this),x;P(' ');print(args...);RT}
};
#undef LL
#undef I
#undef OP
#undef RT
#undef ALL_INT
#undef ALL_FLT
#undef S2D
#undef R2D
#undef R2F
#undef RD_INT
#undef RD_FLT
#undef W4D
#undef WR_INT
#undef WR_FLT
}
fio::Fr<fio::Cg>fin;
fio::Fw<fio::Cp>fout;
fio::Fw<fio::Ce>ferr;
// 	 fout.all(vec)
#include <type_traits>
#ifndef OJLIBS_USE_INT128
#  define OJLIBS_USE_INT128 1
#endif
// try binary gcd on large number
template <typename Int>
Int gcd(Int a, Int b) {
    while (a != 0) {
        b %= a;
        if (b == 0)
            return a;
        a %= b;
    }
    return b;
}
template <typename Int, typename RInt = Int>
Int lcm(Int a, Int b) {
    return a / gcd(a, b) * static_cast<RInt>(b);
}
template <typename Int, typename XInt>
Int extended_gcd(Int a, Int b, XInt &x, XInt &y) {
    static_assert(std::numeric_limits<XInt>::is_signed,
            "x, y must be signed");
    // pre condition : a != 0 || b != 0
    // post condition : a * x + b * y = g
    // (a * x) or (b * y) may overflow, but the condition
    //                 always holds.
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    /**
     * r = a - b * q
     * b * k1 + r * k2 = g
     * => a * k2 + b * (k1 - q * k2)
     *                 x = k2
     *                 y = k1 - q * k2 = k1 - q * x
     */
    Int g = extended_gcd(b, a % b, y, x);
    y -= (a / b) * x;
    return g;
}
template <typename Int>
Int mul_mod(Int a, Int b, Int m) {
    typedef int64_t TInt;
    static_assert(2 * std::numeric_limits<Int>::digits <= std::numeric_limits<TInt>::digits,
            "multiplication will overflow!");
    TInt p = a;
    p = (p * b) % m;
    return (Int)p;
}
#if defined(__SIZEOF_INT128__) && OJLIBS_USE_INT128
template <>
int64_t mul_mod<int64_t>(int64_t a, int64_t b, int64_t m) {
    __int128_t p = __int128_t(a) * b;
    return (int64_t)(p % m);
}
#else
template <>
int64_t mul_mod<int64_t>(int64_t a, int64_t b, int64_t m) {
    int64_t r = 0;
    for (int i = 63; i >= 0; --i) {
        r = (r + r) % m;
        if ((b >> i) & 1)
            r = (r + a) % m;
    }
    return r;
}
#endif
template <typename Int, typename PInt>
Int pow_mod(Int a, PInt p, Int m) {
    Int r;
    a %= m;
    for (r = 1; p; p >>= 1) {
        if (p & 1) r = mul_mod(r, a, m);
        a = mul_mod(a, a, m);
    }
    return r;
}
template <typename Int,
          typename XInt = typename std::make_signed<Int>::type>
Int inv_mod(Int a, Int m) {
    // a * x = gcd(a, m) (mod m)
    XInt x, y;
    extended_gcd(a, m, x, y);
    if (x < 0)
        return x + m;
    return x;
}
template <typename Int>
Int addx_mod(Int u, Int v, Int m) {
    Int r = u + v;
    if (r >= m) r -= m;
    return r;
}
template <typename Int>
Int subx_mod(Int u, Int v, Int m) {
    Int r = u - v;
    if (r < 0) r += m;
    return r;
}
template <typename Int>
Int div_mod(Int u, Int v, Int m) {
    // find x, s.t.
    //     u = v * x (mod m)
    // solution exist
    //     <=> gcd(v, m) | gcd(u, m)
    // g = gcd(v, m)   [do not use gcd(u, v)]
    // uu = u / g
    // vv = v / g
    // mm = m / g
    //     uu = vv * x (mod mm)
    Int g = gcd(v, m);
    assert(u % g == 0);
    Int mm = m / g;
    return mul_mod(u / g, inv_mod(v / g, mm), mm);
}
template <typename Int>
Int div_pos_r(Int a, Int b, Int &r) {
    // 3 / 2  = 1 .. 1 (ok)
    // 3 / -2 = -1 .. 1 (ok)
    // -3 / 2 = -1 .. -1 (not ok)
    // -3 / -2 = 1 .. -1 (not ok)
    // a = q b + r
    //   = (q + 1) b + (r - b)
    //   = (q - 1) b + (r + b)
    Int q = a / b;
    r = a % b;
    if (r < 0) {
        if (b < 0)
            q += 1, r -= b;
        else
            q -= 1, r += b;
    }
    return q;
}
// TODO: gauss_factorial, factorial_mod.
//       log, factorial_exp
#define INV_MOD(x)      inv_mod((x), MOD)
#define MUL_MOD(x, y)   mul_mod((x), (y), MOD)
#define MULM_MOD(x, y)  (x) = mul_mod((x), (y), MOD)
#define POW_MOD(x, y)   pow_mod((x), (y), MOD)
#define ADDX_MOD(x, y)  addx_mod((x), (y), MOD)
#define ADDM_MOD(x, y)  (x) = addx_mod((x), (y), MOD)
#define SUBX_MOD(x, y)  subx_mod((x), (y), MOD)
#define SUBM_MOD(x, y)  (x) = subx_mod((x), (y), MOD)
/* =====  SOLUTION START  ===== */
// formalize:
// dimension analysis:
static const int maxn = 505;
int n, m, MOD;
int cnt[maxn];
int dp[maxn][maxn]; // (row, nr2) -> cnt
char buf[maxn];
int C2(int n) {
    return n * (n - 1) / 2;
}
int main() {
    fin, n, m, MOD;
    FOR0(i, m) {
        fin, buf;
        FOR0(j, n) if (buf[j] == '1') ++cnt[j];
    }
    {
        int nr2 = 0;
        FOR0(i, n) {
            if (cnt[i] > 2) {
                puts("0\n");
                return 0;
            } else if (cnt[i] == 0) ++nr2;
        }
        dp[m - 1][nr2] = 1;
    }
    FOR(i, m, n - 1) {
        FOR(nr2, 0, maxn) {
            // nr1 + 2nr2 = 2 * (n - i)
            // (in the last row)
            int nr1 = 2 * (n - i) - 2 * nr2;
            if (nr1 >= 2) ADDM_MOD(dp[i][nr2],
                    MUL_MOD(dp[i - 1][nr2], C2(nr1)));
            if (nr1 >= 1 && nr2 >= 1) ADDM_MOD(dp[i][nr2 - 1],
                    MUL_MOD(dp[i - 1][nr2], MUL_MOD(nr1, nr2)));
        }
    }
    fout, dp[n - 1][0], endl;
    return 0;
}


/*
 * if you are interested in the reference code here,
 * see https://github.com/georeth/OJLIBS for more information
 *
 * Solution Author : Georeth Chow <georeth2010@gmail.com>
 */
#include <cstdio>
#include <cmath>
#include <climits>      // INT_MIN LLONG_MIN
#include <cfloat>       // DBL_MIN DBL_MAX
#include <cstring>      // memset
#include <cstdlib>      // malloc
#include <cstdint>      // int64_t
#include <cinttypes>    // PRId64 SCNd64
#include <ctime>        // clock
#include <cassert>      // assert
#include <limits>       // numeric_limits
#include <vector>
#include <deque>
#include <map>
#include <set>
#include <tuple>        // pair, tuple
#include <iostream>     // be careful.
                        // mix with cstdio: slowwww...
                        // mix with cstdio + fastio: bug
#include <sstream>
#include <algorithm>
using namespace std;    // use as solution header. name polution is fine.
#ifdef LOCAL_JUDGE
#  define pr_debug(...) fprintf(stderr, __VA_ARGS__)
#  define pr_line() fprintf(stderr, "%s: %d\n", __FILE__, __LINE__)
#else
#  define pr_debug(...)
#  define pr_line()
#endif
template <typename T>
bool chmax(T &m, const T &v) { if (v > m) return m = v, true; return false; }
template <typename T>
bool chmin(T &m, const T &v) { if (v < m) return m = v, true; return false; }
template <typename T>
bool chinc(T &v1, T &v2) { if (v1 > v2) return swap(v1, v2), true; return false; }
template <typename T>
bool chdec(T &v1, T &v2) { if (v1 < v2) return swap(v1, v2), true; return false; }
#define ALL(x) begin(x), end(x)
#define FOR0(i,n) for(int i=0,i##end=n;i<i##end;i++)
#define FOR1(i,n) for(int i=1,i##end=n;i<=i##end;i++)
#define FOR(i,a,b) for(int i=a,i##end=b;i<=i##end;i++)
#define FOD0(i,n) for(int i=(n)-1;~i;i--)
#define FOD1(i,n) for(int i=n;i;i--)
#define FOD(i,a,b) for(int i=a,i##end=b;i>=i##end;i--)
#define FORE(i,x)for(__typeof(x.end())i=x.begin();i!=x.end();++i)
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pair<int, int>> vii;
typedef vector<vector<int>> vvi;
namespace fio {
static const char eof = '\xff';
#define LL long long
#define I inline
#define OP operator
#define RT return*this;
#define ALL_INT(mcr) mcr(int)mcr(long)mcr(LL)mcr(unsigned)mcr(unsigned long)mcr(unsigned LL)
#define ALL_FLT(mcr) mcr(float)mcr(double)mcr(long double)
#define S2D x=0;int c=P();while((c<'0'||c>'9')&&c!='-')c=P();bool h=false;if(c=='-')h=true,c=P()
#define R2D for(;c>='0'&&c<='9';c=P())x=x*10+c-'0'
#define R2F if(c=='.'){double u=0.1;for(c=P();c>='0'&&c<='9';c=P(),u*=0.1)x+=u*(c-'0');}
#define RD_INT(Int) I Fr&OP,(Int&x){S2D;R2D;if(h)x=-x;RT}
#define RD_FLT(Flt) I Fr&OP,(Flt&x){S2D;R2D;R2F;if(h)x=-x;RT}
struct Cg{I char OP()(){char c=(char)getchar();if(c == eof)valid=false;return c;};bool valid=true;};
struct Cp{I void OP()(int x){putchar(x);}};
struct Ce{I void OP()(int x){putc(x,stderr);}};
I bool IS(char x){return x==' '||x=='\r'||x=='\n'||x=='\t';}
template<class T>struct Fr{T P;ALL_INT(RD_INT)ALL_FLT(RD_FLT)I Fr&OP,(char&x){for(x=P();IS(x);)x=P();RT}
I Fr&OP,(char*s){for(*s=P();IS(*s)&&P.valid;)*s=P();for(;!IS(*s)&&P.valid;)*++s=P();*s=0;RT}
I Fr&OP,(string &s){s.clear();char c=P();for(;IS(c)&&P.valid;)c=P();for(;!IS(c)&&P.valid;)s.push_back(c),c=P();RT}
I OP bool() { return P.valid; }
};
#define W4D if(x){if(x<0)P('-'),x=-x;int p=0;while(x)B[p++]=x%10+'0',x/=10;while(p--)P(B[p]);}else P('0')
#define WR_INT(Int) I Fw&OP,(Int x){W4D;RT}
#define WR_FLT(Flt) I Fw&OP()(Flt g,int d){if(d){double t=0.5;for(int i=d;i--;)t*=0.1;if(g<0)P('-'),g=-g;g+=t;*this,(LL)(g);P('.');g-=floor(g);while(d--){g*=10;int i=(int)floor(g);P(i+'0');g-=i;}}else*this,(g>0?(LL)(g+0.5):(LL)(g-0.5));RT}
template<class T>struct Fw{T P;char B[32];ALL_INT(WR_INT)ALL_FLT(WR_FLT)I Fw&OP,(char x){P(x);RT}typedef char_traits<char>CT;typedef basic_ostream<char,CT>&OS;typedef basic_istream<char,CT>&IS;I Fw&OP,(OS&(*func)(OS)){if(func==static_cast<OS&(*)(OS)>(endl<char,CT>))P('\n');RT}I Fw&OP,(IS&(*func)(IS)){if(func==static_cast<IS&(*)(IS)>(ws<char,CT>))P(' ');RT}
I Fw&OP,(const char*s){for(;*s;++s)P(*s);RT}
I Fw&OP,(const string&s){(*this),s.c_str();RT}
template<class C>I Fw&all(const C &v, char sep=' ', char nl='\n'){auto it=v.begin();for(int i=0;i<(int)v.size();++i,++it){if(i&&sep)P(sep);(*this),*it;}if(nl)P(nl);RT}
template<class U>I Fw&print(U x){(*this),x;P('\n');RT}
template<class U,class...Us>I Fw&print(U x,Us...args){(*this),x;P(' ');print(args...);RT}
};
#undef LL
#undef I
#undef OP
#undef RT
#undef ALL_INT
#undef ALL_FLT
#undef S2D
#undef R2D
#undef R2F
#undef RD_INT
#undef RD_FLT
#undef W4D
#undef WR_INT
#undef WR_FLT
}
fio::Fr<fio::Cg>fin;
fio::Fw<fio::Cp>fout;
fio::Fw<fio::Ce>ferr;
// 	 fout.all(vec)
#include <type_traits>
#ifndef OJLIBS_USE_INT128
#  define OJLIBS_USE_INT128 1
#endif
// try binary gcd on large number
template <typename Int>
Int gcd(Int a, Int b) {
    while (a != 0) {
        b %= a;
        if (b == 0)
            return a;
        a %= b;
    }
    return b;
}
template <typename Int, typename RInt = Int>
Int lcm(Int a, Int b) {
    return a / gcd(a, b) * static_cast<RInt>(b);
}
template <typename Int, typename XInt>
Int extended_gcd(Int a, Int b, XInt &x, XInt &y) {
    static_assert(std::numeric_limits<XInt>::is_signed,
            "x, y must be signed");
    // pre condition : a != 0 || b != 0
    // post condition : a * x + b * y = g
    // (a * x) or (b * y) may overflow, but the condition
    //                 always holds.
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    /**
     * r = a - b * q
     * b * k1 + r * k2 = g
     * => a * k2 + b * (k1 - q * k2)
     *                 x = k2
     *                 y = k1 - q * k2 = k1 - q * x
     */
    Int g = extended_gcd(b, a % b, y, x);
    y -= (a / b) * x;
    return g;
}
template <typename Int>
Int mul_mod(Int a, Int b, Int m) {
    typedef int64_t TInt;
    static_assert(2 * std::numeric_limits<Int>::digits <= std::numeric_limits<TInt>::digits,
            "multiplication will overflow!");
    TInt p = a;
    p = (p * b) % m;
    return (Int)p;
}
#if defined(__SIZEOF_INT128__) && OJLIBS_USE_INT128
template <>
int64_t mul_mod<int64_t>(int64_t a, int64_t b, int64_t m) {
    __int128_t p = __int128_t(a) * b;
    return (int64_t)(p % m);
}
#else
template <>
int64_t mul_mod<int64_t>(int64_t a, int64_t b, int64_t m) {
    int64_t r = 0;
    for (int i = 63; i >= 0; --i) {
        r = (r + r) % m;
        if ((b >> i) & 1)
            r = (r + a) % m;
    }
    return r;
}
#endif
template <typename Int, typename PInt>
Int pow_mod(Int a, PInt p, Int m) {
    Int r;
    a %= m;
    for (r = 1; p; p >>= 1) {
        if (p & 1) r = mul_mod(r, a, m);
        a = mul_mod(a, a, m);
    }
    return r;
}
template <typename Int,
          typename XInt = typename std::make_signed<Int>::type>
Int inv_mod(Int a, Int m) {
    // a * x = gcd(a, m) (mod m)
    XInt x, y;
    extended_gcd(a, m, x, y);
    if (x < 0)
        return x + m;
    return x;
}
template <typename Int>
Int addx_mod(Int u, Int v, Int m) {
    Int r = u + v;
    if (r >= m) r -= m;
    return r;
}
template <typename Int>
Int subx_mod(Int u, Int v, Int m) {
    Int r = u - v;
    if (r < 0) r += m;
    return r;
}
template <typename Int>
Int div_mod(Int u, Int v, Int m) {
    // find x, s.t.
    //     u = v * x (mod m)
    // solution exist
    //     <=> gcd(v, m) | gcd(u, m)
    // g = gcd(v, m)   [do not use gcd(u, v)]
    // uu = u / g
    // vv = v / g
    // mm = m / g
    //     uu = vv * x (mod mm)
    Int g = gcd(v, m);
    assert(u % g == 0);
    Int mm = m / g;
    return mul_mod(u / g, inv_mod(v / g, mm), mm);
}
template <typename Int>
Int div_pos_r(Int a, Int b, Int &r) {
    // 3 / 2  = 1 .. 1 (ok)
    // 3 / -2 = -1 .. 1 (ok)
    // -3 / 2 = -1 .. -1 (not ok)
    // -3 / -2 = 1 .. -1 (not ok)
    // a = q b + r
    //   = (q + 1) b + (r - b)
    //   = (q - 1) b + (r + b)
    Int q = a / b;
    r = a % b;
    if (r < 0) {
        if (b < 0)
            q += 1, r -= b;
        else
            q -= 1, r += b;
    }
    return q;
}
// TODO: gauss_factorial, factorial_mod.
//       log, factorial_exp
#define INV_MOD(x)      inv_mod((x), MOD)
#define MUL_MOD(x, y)   mul_mod((x), (y), MOD)
#define MULM_MOD(x, y)  (x) = mul_mod((x), (y), MOD)
#define POW_MOD(x, y)   pow_mod((x), (y), MOD)
#define ADDX_MOD(x, y)  addx_mod((x), (y), MOD)
#define ADDM_MOD(x, y)  (x) = addx_mod((x), (y), MOD)
#define SUBX_MOD(x, y)  subx_mod((x), (y), MOD)
#define SUBM_MOD(x, y)  (x) = subx_mod((x), (y), MOD)
/* =====  SOLUTION START  ===== */
// formalize:
// dimension analysis:
static const int maxn = 100005;
int n, m, MOD;
int cnt[maxn];
int dp[maxn][maxn]; // (row, nr2) -> cnt
char buf[maxn];
int C2(int n) {
    return n * (n - 1) / 2;
}
int main() {
    fin, n, m, MOD;
    FOR0(i, m) {
        fin, buf;
        FOR0(j, n) if (buf[j] == '1') ++cnt[j];
    }
    {
        int nr2 = 0;
        FOR0(i, n) {
            if (cnt[i] > 2) {
                puts("0\n");
                return 0;
            } else if (cnt[i] == 0) ++nr2;
        }
        dp[m - 1][nr2] = 1;
    }
    FOR(i, m, n - 1) {
        FOR(nr2, 0, maxn) {
            // nr1 + 2nr2 = 2 * (n - i)
            // (in the last row)
            int nr1 = 2 * (n - i) - 2 * nr2;
            if (nr1 >= 2) ADDM_MOD(dp[i][nr2],
                    MUL_MOD(dp[i - 1][nr2], C2(nr1)));
            if (nr1 >= 1 && nr2 >= 1) ADDM_MOD(dp[i][nr2 - 1],
                    MUL_MOD(dp[i - 1][nr2], MUL_MOD(nr1, nr2)));
        }
    }
    fout, dp[n - 1][0], endl;
    return 0;
}


/*
 * if you are interested in the reference code here,
 * see https://github.com/georeth/OJLIBS for more information
 *
 * Solution Author : Georeth Chow <georeth2010@gmail.com>
 */
#include <cstdio>
#include <cmath>
#include <climits>      // INT_MIN LLONG_MIN
#include <cfloat>       // DBL_MIN DBL_MAX
#include <cstring>      // memset
#include <cstdlib>      // malloc
#include <cstdint>      // int64_t
#include <cinttypes>    // PRId64 SCNd64
#include <ctime>        // clock
#include <cassert>      // assert
#include <limits>       // numeric_limits
#include <vector>
#include <deque>
#include <map>
#include <set>
#include <tuple>        // pair, tuple
#include <iostream>     // be careful.
                        // mix with cstdio: slowwww...
                        // mix with cstdio + fastio: bug
#include <sstream>
#include <algorithm>
using namespace std;    // use as solution header. name polution is fine.
#ifdef LOCAL_JUDGE
#  define pr_debug(...) fprintf(stderr, __VA_ARGS__)
#  define pr_line() fprintf(stderr, "%s: %d\n", __FILE__, __LINE__)
#else
#  define pr_debug(...)
#  define pr_line()
#endif
template <typename T>
bool chmax(T &m, const T &v) { if (v > m) return m = v, true; return false; }
template <typename T>
bool chmin(T &m, const T &v) { if (v < m) return m = v, true; return false; }
template <typename T>
bool chinc(T &v1, T &v2) { if (v1 > v2) return swap(v1, v2), true; return false; }
template <typename T>
bool chdec(T &v1, T &v2) { if (v1 < v2) return swap(v1, v2), true; return false; }
#define ALL(x) begin(x), end(x)
#define FOR0(i,n) for(int i=0,i##end=n;i<i##end;i++)
#define FOR1(i,n) for(int i=1,i##end=n;i<=i##end;i++)
#define FOR(i,a,b) for(int i=a,i##end=b;i<=i##end;i++)
#define FOD0(i,n) for(int i=(n)-1;~i;i--)
#define FOD1(i,n) for(int i=n;i;i--)
#define FOD(i,a,b) for(int i=a,i##end=b;i>=i##end;i--)
#define FORE(i,x)for(__typeof(x.end())i=x.begin();i!=x.end();++i)
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pair<int, int>> vii;
typedef vector<vector<int>> vvi;
namespace fio {
static const char eof = '\xff';
#define LL long long
#define I inline
#define OP operator
#define RT return*this;
#define ALL_INT(mcr) mcr(int)mcr(long)mcr(LL)mcr(unsigned)mcr(unsigned long)mcr(unsigned LL)
#define ALL_FLT(mcr) mcr(float)mcr(double)mcr(long double)
#define S2D x=0;int c=P();while((c<'0'||c>'9')&&c!='-')c=P();bool h=false;if(c=='-')h=true,c=P()
#define R2D for(;c>='0'&&c<='9';c=P())x=x*10+c-'0'
#define R2F if(c=='.'){double u=0.1;for(c=P();c>='0'&&c<='9';c=P(),u*=0.1)x+=u*(c-'0');}
#define RD_INT(Int) I Fr&OP,(Int&x){S2D;R2D;if(h)x=-x;RT}
#define RD_FLT(Flt) I Fr&OP,(Flt&x){S2D;R2D;R2F;if(h)x=-x;RT}
struct Cg{I char OP()(){char c=(char)getchar();if(c == eof)valid=false;return c;};bool valid=true;};
struct Cp{I void OP()(int x){putchar(x);}};
struct Ce{I void OP()(int x){putc(x,stderr);}};
I bool IS(char x){return x==' '||x=='\r'||x=='\n'||x=='\t';}
template<class T>struct Fr{T P;ALL_INT(RD_INT)ALL_FLT(RD_FLT)I Fr&OP,(char&x){for(x=P();IS(x);)x=P();RT}
I Fr&OP,(char*s){for(*s=P();IS(*s)&&P.valid;)*s=P();for(;!IS(*s)&&P.valid;)*++s=P();*s=0;RT}
I Fr&OP,(string &s){s.clear();char c=P();for(;IS(c)&&P.valid;)c=P();for(;!IS(c)&&P.valid;)s.push_back(c),c=P();RT}
I OP bool() { return P.valid; }
};
#define W4D if(x){if(x<0)P('-'),x=-x;int p=0;while(x)B[p++]=x%10+'0',x/=10;while(p--)P(B[p]);}else P('0')
#define WR_INT(Int) I Fw&OP,(Int x){W4D;RT}
#define WR_FLT(Flt) I Fw&OP()(Flt g,int d){if(d){double t=0.5;for(int i=d;i--;)t*=0.1;if(g<0)P('-'),g=-g;g+=t;*this,(LL)(g);P('.');g-=floor(g);while(d--){g*=10;int i=(int)floor(g);P(i+'0');g-=i;}}else*this,(g>0?(LL)(g+0.5):(LL)(g-0.5));RT}
template<class T>struct Fw{T P;char B[32];ALL_INT(WR_INT)ALL_FLT(WR_FLT)I Fw&OP,(char x){P(x);RT}typedef char_traits<char>CT;typedef basic_ostream<char,CT>&OS;typedef basic_istream<char,CT>&IS;I Fw&OP,(OS&(*func)(OS)){if(func==static_cast<OS&(*)(OS)>(endl<char,CT>))P('\n');RT}I Fw&OP,(IS&(*func)(IS)){if(func==static_cast<IS&(*)(IS)>(ws<char,CT>))P(' ');RT}
I Fw&OP,(const char*s){for(;*s;++s)P(*s);RT}
I Fw&OP,(const string&s){(*this),s.c_str();RT}
template<class C>I Fw&all(const C &v, char sep=' ', char nl='\n'){auto it=v.begin();for(int i=0;i<(int)v.size();++i,++it){if(i&&sep)P(sep);(*this),*it;}if(nl)P(nl);RT}
template<class U>I Fw&print(U x){(*this),x;P('\n');RT}
template<class U,class...Us>I Fw&print(U x,Us...args){(*this),x;P(' ');print(args...);RT}
};
#undef LL
#undef I
#undef OP
#undef RT
#undef ALL_INT
#undef ALL_FLT
#undef S2D
#undef R2D
#undef R2F
#undef RD_INT
#undef RD_FLT
#undef W4D
#undef WR_INT
#undef WR_FLT
}
fio::Fr<fio::Cg>fin;
fio::Fw<fio::Cp>fout;
fio::Fw<fio::Ce>ferr;
// 	 fout.all(vec)
#include <type_traits>
#ifndef OJLIBS_USE_INT128
#  define OJLIBS_USE_INT128 1
#endif
// try binary gcd on large number
template <typename Int>
Int gcd(Int a, Int b) {
    while (a != 0) {
        b %= a;
        if (b == 0)
            return a;
        a %= b;
    }
    return b;
}
template <typename Int, typename RInt = Int>
Int lcm(Int a, Int b) {
    return a / gcd(a, b) * static_cast<RInt>(b);
}
template <typename Int, typename XInt>
Int extended_gcd(Int a, Int b, XInt &x, XInt &y) {
    static_assert(std::numeric_limits<XInt>::is_signed,
            "x, y must be signed");
    // pre condition : a != 0 || b != 0
    // post condition : a * x + b * y = g
    // (a * x) or (b * y) may overflow, but the condition
    //                 always holds.
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    /**
     * r = a - b * q
     * b * k1 + r * k2 = g
     * => a * k2 + b * (k1 - q * k2)
     *                 x = k2
     *                 y = k1 - q * k2 = k1 - q * x
     */
    Int g = extended_gcd(b, a % b, y, x);
    y -= (a / b) * x;
    return g;
}
template <typename Int>
Int mul_mod(Int a, Int b, Int m) {
    typedef int64_t TInt;
    static_assert(2 * std::numeric_limits<Int>::digits <= std::numeric_limits<TInt>::digits,
            "multiplication will overflow!");
    TInt p = a;
    p = (p * b) % m;
    return (Int)p;
}
#if defined(__SIZEOF_INT128__) && OJLIBS_USE_INT128
template <>
int64_t mul_mod<int64_t>(int64_t a, int64_t b, int64_t m) {
    __int128_t p = __int128_t(a) * b;
    return (int64_t)(p % m);
}
#else
template <>
int64_t mul_mod<int64_t>(int64_t a, int64_t b, int64_t m) {
    int64_t r = 0;
    for (int i = 63; i >= 0; --i) {
        r = (r + r) % m;
        if ((b >> i) & 1)
            r = (r + a) % m;
    }
    return r;
}
#endif
template <typename Int, typename PInt>
Int pow_mod(Int a, PInt p, Int m) {
    Int r;
    a %= m;
    for (r = 1; p; p >>= 1) {
        if (p & 1) r = mul_mod(r, a, m);
        a = mul_mod(a, a, m);
    }
    return r;
}
template <typename Int,
          typename XInt = typename std::make_signed<Int>::type>
Int inv_mod(Int a, Int m) {
    // a * x = gcd(a, m) (mod m)
    XInt x, y;
    extended_gcd(a, m, x, y);
    if (x < 0)
        return x + m;
    return x;
}
template <typename Int>
Int addx_mod(Int u, Int v, Int m) {
    Int r = u + v;
    if (r >= m) r -= m;
    return r;
}
template <typename Int>
Int subx_mod(Int u, Int v, Int m) {
    Int r = u - v;
    if (r < 0) r += m;
    return r;
}
template <typename Int>
Int div_mod(Int u, Int v, Int m) {
    // find x, s.t.
    //     u = v * x (mod m)
    // solution exist
    //     <=> gcd(v, m) | gcd(u, m)
    // g = gcd(v, m)   [do not use gcd(u, v)]
    // uu = u / g
    // vv = v / g
    // mm = m / g
    //     uu = vv * x (mod mm)
    Int g = gcd(v, m);
    assert(u % g == 0);
    Int mm = m / g;
    return mul_mod(u / g, inv_mod(v / g, mm), mm);
}
template <typename Int>
Int div_pos_r(Int a, Int b, Int &r) {
    // 3 / 2  = 1 .. 1 (ok)
    // 3 / -2 = -1 .. 1 (ok)
    // -3 / 2 = -1 .. -1 (not ok)
    // -3 / -2 = 1 .. -1 (not ok)
    // a = q b + r
    //   = (q + 1) b + (r - b)
    //   = (q - 1) b + (r + b)
    Int q = a / b;
    r = a % b;
    if (r < 0) {
        if (b < 0)
            q += 1, r -= b;
        else
            q -= 1, r += b;
    }
    return q;
}
// TODO: gauss_factorial, factorial_mod.
//       log, factorial_exp
#define INV_MOD(x)      inv_mod((x), MOD)
#define MUL_MOD(x, y)   mul_mod((x), (y), MOD)
#define MULM_MOD(x, y)  (x) = mul_mod((x), (y), MOD)
#define POW_MOD(x, y)   pow_mod((x), (y), MOD)
#define ADDX_MOD(x, y)  addx_mod((x), (y), MOD)
#define ADDM_MOD(x, y)  (x) = addx_mod((x), (y), MOD)
#define SUBX_MOD(x, y)  subx_mod((x), (y), MOD)
#define SUBM_MOD(x, y)  (x) = subx_mod((x), (y), MOD)
/* =====  SOLUTION START  ===== */
// formalize:
// dimension analysis:
static const int maxn = 505;
int n, m, MOD;
int cnt[maxn];
int dp[maxn][maxn]; // (row, nr2) -> cnt
char buf[maxn];
int C2(int n) {
    return n * (n - 1) / 2;
}
int main() {
    fin, n, m, MOD;
    FOR0(i, m) {
        fin, buf;
        FOR0(j, n) if (buf[j] == '1') ++cnt[j];
    }
    {
        int nr2 = 0;
        FOR0(i, n) {
            if (cnt[i] > 2) {
                puts("0\n");
                return 0;
            } else if (cnt[i] == 0) ++nr2;
        }
        dp[m][nr2] = 1;
    }
    FOR(i, m + 1, n) {
        FOR(nr2, 0, n) {
            // nr1 + 2nr2 = 2 * (n - i + 1)
            // (in the last row)
            int nr1 = 2 * (n - i + 1) - 2 * nr2;
            if (nr1 < 0) continue;
            if (nr1 >= 2) ADDM_MOD(dp[i][nr2],
                    MUL_MOD(dp[i - 1][nr2], C2(nr1)));
            if (nr2 >= 2) ADDM_MOD(dp[i][nr2 - 2],
                    MUL_MOD(dp[i - 1][nr2], C2(nr2)));
            if (nr1 >= 1 && nr2 >= 1) ADDM_MOD(dp[i][nr2 - 1],
                    MUL_MOD(dp[i - 1][nr2], MUL_MOD(nr1, nr2)));
        }
    }
    fout, dp[n][0], endl;
    return 0;
}


#include<bits/stdc++.h>
#define FOR(x,y,z) for(int x=y;x<=z;x++)
#define DOR(x,y,z) for(int x=y;x>=z;x--)
#define read2(x,y) read(x),read(y)
#define read3(x,y,z) read(x),read(y),read(z)
#define db double
#define ll long long
using namespace std;
const int maxn=505;
void read(int &x){
	scanf("%d",&x);
}
int n,m,P;
int cnt[maxn],res[3];
ll dp[maxn][maxn];
char str[maxn];
int main(){
	read3(n,m,P);
	FOR(i,1,m){
		scanf("%s",str+1);
		FOR(j,1,n)cnt[j]+=str[j]^48;
	}
	FOR(i,1,n)res[2-cnt[i]]++;
	dp[res[2]][res[1]]=1;
	DOR(i,n,0)DOR(j,n-i,0){
		if(i>=2)(dp[i-2][j+2]+=dp[i][j]*i*(i-1)/2)%=P;
		if(i>=1)(dp[i-1][j]+=dp[i][j]*i*j)%=P;
		if(j>=2)(dp[i][j-2]+=dp[i][j]*j*(j-1)/2)%=P;
//		printf("dp[%d][%d]=%lld\n",i,j,dp[i][j]);
	}printf("%lld",dp[0][0]);
}


#include<bits/stdc++.h>
#define FOR(x,y,z) for(int x=y;x<=z;x++)
#define DOR(x,y,z) for(int x=y;x>=z;x--)
#define read2(x,y) read(x),read(y)
#define read3(x,y,z) read(x),read(y),read(z)
#define db double
#define ll long long
using namespace std;
void read(int &x){
	scanf("%d",&x);
}
ll dp[40][40];
int n,h;
int main(){
	read2(n,h);
	dp[0][0]=1;
	dp[1][1]=1;
	FOR(i,2,n)FOR(j,1,i){
		FOR(k,0,i-1){
			dp[i][j]+=dp[k][j-1]*dp[i-1-k][j-1];
			FOR(p,0,min(k,j-2))
				dp[i][j]+=dp[k][p]*dp[i-1-k][j-1];
			FOR(q,0,min(i-1-k,j-2))
				dp[i][j]+=dp[k][j-1]*dp[i-1-k][q];
		}
//		printf("dp[%d][%d]=%lld\n",i,j,dp[i][j]);
	}
	ll ans=0;
	FOR(i,h,n)ans+=dp[n][i];
	printf("%lld",ans);
}


#include <bits/stdc++.h>
using namespace std;
#define e1 first
#define e2 second
#define pb push_back
#define mp make_pair
#define boost ios_base::sync_with_stdio(false)
#define eb emplace_back
#define OUT(x) {cout << x; exit(0); }
#define FOR(i, a, b) for(int i=(a); i<=(b); ++i)
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> PII;
typedef pair <ll, ll> PLL;
typedef pair <PLL, PLL> PP;
typedef unsigned int ui;
const int inf = 1e9+9;
const ll MOD = 1e9+696969;
const ll INF = 1e18;
#define maxn 510
int dp[maxn][maxn], odp[maxn][maxn], n, m, mod;

int ile[maxn];
char s[maxn][maxn];

int main()
{
	scanf("%d%d%d", &n, &m, &mod);
	FOR(i, 1, m) scanf("%s", s[i] + 1);
	FOR(i, 1, m)
	  FOR(j, 1, n) ile[j] += s[i][j] - '0';

	FOR(i, 1, n)
	  if (ile[i] > 2) OUT(0);

	int id = 0, ij = 0;
	FOR(i, 1, n)
	{
	  	if (ile[i] == 0) ++id;
	  	if (ile[i] == 1) ++ij;
	}
	//cout << id << ' ' << ij << endl;
	odp[id][ij] = 1;
	FOR(steps, m+1, n)
	{
		FOR(i, 0, id)
		  FOR(j, 0, n)
		  {
		  		int bin = (j + 2) * (j + 1) / 2;
		  		ll val = odp[i][j+2];
		  		val = (val * bin)%mod;
		  		dp[i][j] = val;

		  		val = odp[i+1][j];
		  		val = (val * (i+1) * j)%mod;
		  		dp[i][j] += val;
		  		while (dp[i][j] >= mod) dp[i][j] -= mod;

		  		if (j - 2 >= 0)
				{
					val = odp[i+2][j-2];
		  			bin = (i + 2) * (i + 1) / 2;
		  			val = (val * bin)%mod;
		  			dp[i][j] += val;
		  			while (dp[i][j] >= mod) dp[i][j] -= mod;
		  		}

		  		//if (dp[i][j] > 0) cout << dp[i][j] << " WSK : " << i << ' ' << j << endl;
		  }
		FOR(i, 0, id)
		  FOR(j, 0, n) odp[i][j] = dp[i][j];
	//	cout << "ENDSTEP\n";
	}

	cout << odp[0][0];
}