You are given an integer m.

Let M = 2m - 1.

You are also given a set of n integers denoted as the set T. The integers will be provided in base 2 as n binary strings of length m.

A set of integers S is called "good" if the following hold. 

  1. If <image>, then <image>. 
  2. If <image>, then <image>
  3. <image>
  4. All elements of S are less than or equal to M. 



Here, <image> and <image> refer to the bitwise XOR and bitwise AND operators, respectively.

Count the number of good sets S, modulo 109 + 7.

Input

The first line will contain two integers m and n (1 ≤ m ≤ 1 000, 1 ≤ n ≤ min(2m, 50)).

The next n lines will contain the elements of T. Each line will contain exactly m zeros and ones. Elements of T will be distinct.

Output

Print a single integer, the number of good sets modulo 109 + 7. 

Examples

Input

5 3
11010
00101
11000


Output

4


Input

30 2
010101010101010010101010101010
110110110110110011011011011011


Output

860616440

Note

An example of a valid set S is {00000, 00101, 00010, 00111, 11000, 11010, 11101, 11111}.
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.io.BufferedWriter;
import java.util.Random;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Jialin Ouyang (Jialin.Ouyang@gmail.com)
 */
public class Main {
  public static void main(String[] args) {
    InputStream inputStream = System.in;
    OutputStream outputStream = System.out;
    QuickScanner in = new QuickScanner(inputStream);
    QuickWriter out = new QuickWriter(outputStream);
    TaskE solver = new TaskE();
    solver.solve(1, in, out);
    out.close();
  }

  static class TaskE {
    IntModular MOD;
    BellModular BELL;
    int m;
    int n;
    long[] mask;
    int[] cnt;
    int setCnt;

    public void solve(int testNumber, QuickScanner in, QuickWriter out) {
      m = in.nextInt();
      n = in.nextInt();
      mask = new long[m];
      cnt = new int[m];
      for (int i = 0; i < n; ++i)
        for (int j = 0; j < m; ++j)
          if (in.nextNonSpaceChar() == '1') {
            mask[j] |= 1L << i;
          }
      LongArrayUtils.sort(mask);
      setCnt = LongArrayUtils.unique(mask, cnt);
      MOD = new IntModular();
      BELL = new BellModular(1000, MOD);
      int res = 1;
      for (int i = 0; i < setCnt; ++i) {
        res = MOD.mul(res, BELL.get(cnt[i]));
      }
      out.println(res);
    }

  }

  static class IntArrayUtils {
    public static void swap(int[] values, int uIdx, int vIdx) {
      if (uIdx == vIdx) return;
      values[uIdx] ^= values[vIdx];
      values[vIdx] ^= values[uIdx];
      values[uIdx] ^= values[vIdx];
    }

  }

  static class FactorialModular {
    private static final int MOD = 1000000007;
    private final IntModular mod;
    private int[] fact;
    private int[] invFact;

    public FactorialModular(int n) {
      this(n, MOD);
    }

    public FactorialModular(int n, int mod) {
      this(n, new IntModular(mod));
    }

    public FactorialModular(int n, IntModular mod) {
      this.mod = mod;
      fact = new int[n + 1];
      invFact = new int[n + 1];
      fact[0] = 1;
      for (int i = 1; i <= n; ++i) {
        fact[i] = this.mod.mul(fact[i - 1], i);
      }
      invFact[n] = this.mod.inverse(fact[n]);
      for (int i = n; i > 0; --i) {
        invFact[i - 1] = this.mod.mul(invFact[i], i);
      }
    }

    public int fact(int n) {
      ensureCapacity(n + 1);
      return fact[n];
    }

    public int invFact(int n) {
      ensureCapacity(n + 1);
      return invFact[n];
    }

    private void ensureCapacity(int size) {
      if (size <= fact.length) return;
      size = IntUtils.nextPow2(size);
      int[] newFact = new int[size];
      int[] newInvFact = new int[size];
      for (int i = 0; i < fact.length; ++i) {
        newFact[i] = fact[i];
        newInvFact[i] = invFact[i];
      }
      for (int i = fact.length; i < size; ++i) {
        newFact[i] = mod.mul(newFact[i - 1], fact[i]);
      }
      newInvFact[size - 1] = mod.inverse(newFact[size - 1]);
      for (int i = size - 1; i > fact.length; --i) {
        newInvFact[i - 1] = mod.mul(newInvFact[i], i);
      }
      fact = newFact;
      invFact = newInvFact;
    }

  }

  static class QuickScanner {
    private static final int BUFFER_SIZE = 1024;
    private InputStream stream;
    private byte[] buffer;
    private int currentPosition;
    private int numberOfChars;

    public QuickScanner(InputStream stream) {
      this.stream = stream;
      this.buffer = new byte[BUFFER_SIZE];
      this.currentPosition = 0;
      this.numberOfChars = 0;
    }

    public int nextInt() {
      int c = nextNonSpaceChar();
      boolean positive = true;
      if (c == '-') {
        positive = false;
        c = nextChar();
      }
      int res = 0;
      do {
        if (c < '0' || '9' < c) throw new RuntimeException();
        res = res * 10 + (c - '0');
        c = nextChar();
      } while (!isSpaceChar(c));
      return positive ? res : -res;
    }

    public int nextNonSpaceChar() {
      int res = nextChar();
      for (; isSpaceChar(res) || res < 0; res = nextChar()) ;
      return res;
    }

    public int nextChar() {
      if (numberOfChars == -1) {
        throw new RuntimeException();
      }
      if (currentPosition >= numberOfChars) {
        currentPosition = 0;
        try {
          numberOfChars = stream.read(buffer);
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
        if (numberOfChars <= 0) {
          return -1;
        }
      }
      return buffer[currentPosition++];
    }

    public boolean isSpaceChar(int c) {
      return c == ' ' || c == '\t' || isEndOfLineChar(c);
    }

    public boolean isEndOfLineChar(int c) {
      return c == '\n' || c == '\r' || c < 0;
    }

  }

  static class IntModular {
    private static final int MOD = 1000000007;
    public final int mod;
    private final int[] x;

    public IntModular() {
      this(MOD);
    }

    public IntModular(int mod) {
      this.mod = mod;
      this.x = new int[2];
    }

    public int add(int a, int b) {
      return fix(a + b, mod);
    }

    public int mul(int a, int b) {
      return mul(a, b, mod);
    }

    public int inverse(int a) {
      if (extGcd(a, mod, x) != 1) {
        throw new IllegalArgumentException();
      }
      return slightFix(x[0], mod);
    }

    public int extGcd(int a, int b, int[] x) {
      if (b == 0) {
        x[0] = 1;
        x[1] = 0;
        return a;
      }
      int gcd = extGcd(b, a % b, x);
      IntArrayUtils.swap(x, 0, 1);
      x[1] -= a / b * x[0];
      return gcd;
    }

    public static int mul(int a, int b, int mod) {
      return a > 0
          ? (b < mod / a ? a * b : (int) ((long) a * b % mod))
          : 0;
    }

    public static int fix(int a, int mod) {
      a = slightFix(a, mod);
      return 0 <= a && a < mod ? a : slightFix(a % mod, mod);
    }

    private static int slightFix(int a, int mod) {
      return a >= mod
          ? a - mod
          : a < 0 ? a + mod : a;
    }

  }

  static class QuickWriter {
    private final PrintWriter writer;

    public QuickWriter(OutputStream outputStream) {
      this.writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public QuickWriter(Writer writer) {
      this.writer = new PrintWriter(writer);
    }

    public void print(Object... objects) {
      for (int i = 0; i < objects.length; ++i) {
        if (i > 0) {
          writer.print(' ');
        }
        writer.print(objects[i]);
      }
    }

    public void println(Object... objects) {
      print(objects);
      writer.println();
    }

    public void close() {
      writer.close();
    }

  }

  static class LongArrayUtils {
    private static final Random RANDOM = new Random(1000000007);

    public static void sort(long[] values) {
      sort(values, 0, values.length);
    }

    public static void sort(long[] values, int fromIdx, int toIdx) {
      shuffle(values, fromIdx, toIdx);
      Arrays.sort(values, fromIdx, toIdx);
    }

    public static int unique(long[] values, int[] cnt) {
      return unique(values, 0, values.length, cnt, 0);
    }

    public static int unique(long[] values, int fromIdx, int toIdx, int[] cnt, int startIdx) {
      if (fromIdx == toIdx) return 0;
      int res = 1;
      cnt[startIdx] = 1;
      for (int i = fromIdx + 1; i < toIdx; ++i) {
        if (values[i - 1] != values[i]) {
          values[fromIdx + res++] = values[i];
          cnt[++startIdx] = 1;
        } else {
          ++cnt[startIdx];
        }
      }
      return res;
    }

    public static void swap(long[] values, int uIdx, int vIdx) {
      if (uIdx == vIdx) return;
      values[uIdx] ^= values[vIdx];
      values[vIdx] ^= values[uIdx];
      values[uIdx] ^= values[vIdx];
    }

    public static void shuffle(long[] values, int fromIdx, int toIdx) {
      for (int i = toIdx - fromIdx - 1; i > 0; --i) {
        swap(values, i + fromIdx, RANDOM.nextInt(i + 1) + fromIdx);
      }
    }

  }

  static class BinomialModular {
    private static final int MOD = 1000000007;
    private final IntModular mod;
    private final FactorialModular fact;

    public BinomialModular(int n) {
      this(n, MOD);
    }

    public BinomialModular(int n, int mod) {
      this(n, new IntModular(mod));
    }

    public BinomialModular(int n, IntModular mod) {
      this.mod = mod;
      this.fact = new FactorialModular(n, mod);
    }

    public int get(int n, int m) {
      if (m > n) return 0;
      return mod.mul(mod.mul(
          fact.fact(n),
          fact.invFact(m)),
          fact.invFact(n - m));
    }

  }

  static class IntUtils {
    public static boolean isPow2(int n) {
      return n > 0 && (n & (n - 1)) == 0;
    }

    public static int nextPow2(int n) {
      if (n < 1) return 1;
      return isPow2(n) ? n : Integer.highestOneBit(n) << 1;
    }

  }

  static class BellModular {
    private static final int MOD = 1000000007;
    private final IntModular mod;
    private final BinomialModular binomial;
    private int[] bell;

    public BellModular(int n) {
      this(n, MOD);
    }

    public BellModular(int n, int mod) {
      this(n, new IntModular(mod));
    }

    public BellModular(int n, IntModular mod) {
      this.mod = mod;
      this.binomial = new BinomialModular(n, mod);
      bell = new int[n + 1];
      bell[0] = 1;
      for (int i = 1; i <= n; ++i) {
        bell[i] = calc(i);
      }
    }

    public int get(int n) {
      ensureCapacity(n + 1);
      return bell[n];
    }

    private int calc(int idx) {
      int res = 0;
      for (int i = 0; i < idx; ++i) {
        res = mod.add(
            res,
            mod.mul(
                bell[i],
                binomial.get(idx - 1, i)));
      }
      return res;
    }

    private void ensureCapacity(int size) {
      if (size <= bell.length) return;
      size = IntUtils.nextPow2(size);
      int[] newBell = new int[size];
      for (int i = 0; i < bell.length; ++i) {
        newBell[i] = bell[i];
      }
      int oldSize = bell.length;
      bell = newBell;
      for (int i = oldSize; i < size; ++i) {
        bell[i] = calc(i);
      }
    }

  }
}

