#include <bits/stdc++.h>
using namespace std;
template <typename T>
void dbg(const string& n, T t) {
  cerr << n << " = " << t << "\n";
}
template <typename T, typename... Types>
void dbg(const string& n, T t, Types... rest) {
  auto x = n.find('('), c = n.find(',');
  if (x != string::npos && x < c)
    for (long long r = 0, l = 0, g = 0; !g or l; c = r++ + 1)
      if (n[r] == '(')
        l++, g = 1;
      else if (n[c] == ')')
        l--;
  cerr << n.substr(0, c++) << " = " << t << ", ";
  dbg(string(n, n.find_first_not_of(" \t\n", c)), rest...);
}
template <typename T1, typename T2>
ostream& operator<<(ostream& o, const pair<T1, T2>& p) {
  return o << "(" << p.first << ", " << p.second << ")";
}
template <typename T>
ostream& operator<<(ostream& o, const vector<T>& v) {
  long long f = 0;
  o << "{";
  for (T x : v) {
    if (f) o << ", ";
    o << x;
    f = 1;
  }
  return o << "}";
}
template <typename T>
ostream& operator<<(ostream& o, queue<T> q) {
  long long f = 0;
  o << "{";
  while (q.size()) {
    if (f) o << ", ";
    o << q.front();
    q.pop();
    f = 1;
  }
  return o << "}";
}
template <typename T>
ostream& operator<<(ostream& o, stack<T> s) {
  long long f = 0;
  o << "{";
  while (s.size()) {
    if (f) o << ", ";
    o << s.top();
    s.pop();
    f = 1;
  }
  return o << "}";
}
template <typename T>
ostream& operator<<(ostream& o, const set<T>& s) {
  long long f = 0;
  o << "{";
  for (T x : s) {
    if (f) o << ", ";
    o << x;
    f = 1;
  }
  return o << "}";
}
template <typename T>
ostream& operator<<(ostream& o, const multiset<T>& s) {
  long long f = 0;
  o << "{";
  for (T x : s) {
    if (f) o << ", ";
    o << x;
    f = 1;
  }
  return o << "}";
}
template <typename T1, typename T2>
ostream& operator<<(ostream& o, const map<T1, T2>& m) {
  for (auto i : m) o << "\n" << i.first << " --> " << i.second;
  return o;
}
template <typename T1, typename T2>
ostream& operator<<(ostream& o, const multimap<T1, T2>& m) {
  for (auto i : m) o << "\n" << i.first << " --> " << i.second;
  return o;
}
string bi(long long n, long long l = -1) {
  string r = "";
  long long f = 1;
  if (!~l) l = 63, f = 0;
  for (long long i = l - 1, c; i >= 0; i--) {
    c = n >> i & 1ll;
    if (r != "")
      r += '0' + c, l--;
    else if (c)
      r += '1', l--;
  }
  while (f and l--) r = "0" + r;
  return (r == "") ? "0" : r;
}
const long long mod = 1e9 + 7;
map<long long, long long> ru;
const long long N = 1000 + 23;
long long bell[N];
long long comb[N][N];
inline void add(long long& a, long long b) {
  a += b;
  if (a >= mod) a -= mod;
}
int main() {
  for (long long i = 0; i < N; i++) {
    comb[i][0] = comb[i][i] = 1;
    for (long long j = 1; j < i; j++)
      comb[i][j] = (comb[i - 1][j] + comb[i - 1][j - 1]) % mod;
  }
  bell[0] = 1;
  for (long long i = 1; i < N; i++)
    for (long long j = 0; j <= i - 1; j++)
      add(bell[i], comb[i - 1][j] * bell[j] % mod);
  long long m, n;
  cin >> m >> n;
  long long id[m];
  for (long long i = 0; i < m; i++) id[i] = 0;
  for (long long i = 0; i < n; i++) {
    string s;
    cin >> s;
    for (long long j = 0; j < m; j++)
      if (s[j] == '1') id[j] |= (1ll << i);
  }
  for (long long i = 0; i < m; i++) ru[id[i]]++;
  long long ret = 1;
  for (pair<long long, long long> k : ru) ret = ret * bell[k.second] % mod;
  cout << ret << "\n";
  return 0;
}
