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.* ;
import java.util.* ;
import java.text.* ;
import java.math.* ;
import static java.lang.Math.min ;
import static java.lang.Math.max ;
public class Codeshefcode{
	public static void main(String[] args) throws IOException{
		Solver Machine = new Solver() ;
		Machine.Solve() ;
		Machine.Finish() ;
		// new Thread(null,new Runnable(){
		// 	public void run(){
		// 		Solver Machine = new Solver() ;
		// 		try{
		// 			Machine.Solve() ;
		// 			Machine.Finish() ;
		// 		}catch(Exception e){
		// 			e.printStackTrace() ;
		// 			System.out.flush() ;
		// 			System.exit(-1) ;
		// 		}catch(Error e){
		// 			e.printStackTrace() ;
		// 			System.out.flush() ;
		// 			System.exit(-1) ;
		// 		}
		// 	}
		// },"Solver",1l<<27).start() ;
	}
}
class Mod{
	static long mod=1000000007 ;
	static long d(long a,long b){ return (a*MI(b))%mod ; }
	static long m(long a,long b){ return (a*b)%mod ; }
	static private long MI(long a){ return pow(a,mod-2) ; }
	static long pow(long a,long b){
		if(b<0) return pow(MI(a),-b) ;
		long val=a ; long ans=1 ;
		while(b!=0){
			if((b&1)==1) ans = (ans*val)%mod ; 
			val = (val*val)%mod ; 
			b/=2 ;
		}
		return ans ;
	}	
}
class pair implements Comparable<pair>{
	int x ; int y ; 
	pair(int x,int y){ this.x=x ; this.y=y ;} 
	public int compareTo(pair p){
		return (this.x<p.x ? -1 : (this.x>p.x ? 1 : (this.y<p.y ? -1 : (this.y>p.y ? 1 : 0)))) ;
	}
}
class Solver{
	Reader ip = new Reader(System.in) ;	  
	PrintWriter op = new PrintWriter(System.out) ;
	int MAX = 1000 ;
	long dp[][] = new long[MAX+1][MAX+1] ;
	long bell[] = new long[MAX+1] ;
	void fill(){
		for(int i=1 ; i<=MAX ; i++) dp[i][1] = 1 ;
		for(int i=1 ; i<=MAX ; i++)
			for(int j=2 ; j<=i ; j++)
				dp[i][j] = (dp[i-1][j-1]+(dp[i-1][j]*j)%Mod.mod)%Mod.mod ;
		bell[0]=1 ;
		for(int i=1 ; i<=MAX ; i++){
			long sm=0 ;
			for(int j=1 ; j<=i ; j++) sm = (sm+dp[i][j])%Mod.mod ;
			bell[i]=sm ;
		}
	}
	public void Solve() throws IOException{
		fill() ;
		int m = ip.i() ; int n = ip.i() ;
		int bits[][] = new int[n][m] ;
		for(int i=0 ; i<n ; i++){
			char c[] = ip.s().toCharArray() ;
			for(int j=0 ; j<m ; j++)
				bits[i][j] = c[j]-'0' ;
 		}
 		int comp[] = new int[m] ;
 		Arrays.fill(comp,-1) ;
 		int mrk=0 ;
 		for(int i=0 ; i<m ; i++){
 			if(comp[i]==-1){
 				int str[] = new int[m] ;
 				Arrays.fill(str,1) ;
 				for(int j=0 ; j<n ; j++)
 					if(bits[j][i]==1)
 						str = and(str,bits[j]) ;
 				int str1[] = new int[m] ;
 				for(int j=0 ; j<n ; j++)
 					if(bits[j][i]==0)
 						str1 = or(str1,bits[j]) ;
 				for(int j=0 ; j<m ; j++) 
 					if(str[j]==1 && str1[j]==0) 
 						str[j]=1 ;
 					else 
 						str[j]=0 ;
 				for(int j=0 ; j<m ; j++)
 					if(str[j]==1)
 						comp[j]=mrk ;
 				mrk++ ;
 			}
 		}
 		int hit[] = new int[mrk] ;
 		for(int i=0 ; i<m ; i++) hit[comp[i]]++ ;
 		long res=1 ;
 		for(int i=0 ; i<mrk ; i++) res = Mod.m(res,bell[hit[i]]) ;
 		pln(res) ;
	}
	int[] or(int a1[],int a2[]){
		int m = a1.length ;
		int a[] = new int[m] ;
		for(int i=0 ; i<m ; i++)
			if(a1[i]==1 || a2[i]==1)
				a[i]=1 ;
		return a ; 
	}
	int[] and(int a1[],int a2[]){
		int m = a1.length ;
		int a[] = new int[m] ;
		for(int i=0 ; i<m ; i++)
			if(a1[i]==1 && a2[i]==1)
				a[i]=1 ;
		return a ; 
	}
	void Finish(){
		op.flush();
		op.close();
	}
	void p(Object o){
		op.print(o) ;
	}
	void pln(Object o){
		op.println(o) ;
	}		
}
class mylist extends ArrayList<Integer>{}
class myset extends TreeSet<Integer>{}
class mystack extends Stack<Integer>{}
class mymap extends TreeMap<Long,Integer>{}
class Reader{
	BufferedReader reader;
	StringTokenizer tokenizer;
	Reader(InputStream input) {
		reader = new BufferedReader(
					new InputStreamReader(input) );
		tokenizer = new StringTokenizer("") ;
	}
	String s() throws IOException {
		while (!tokenizer.hasMoreTokens()){
			tokenizer = new StringTokenizer(
			reader.readLine()) ;
		}
		return tokenizer.nextToken();
	}
	int i() throws IOException {
		return Integer.parseInt(s()) ;
	}
	long l() throws IOException{
		return Long.parseLong(s()) ;
	}
	double d() throws IOException {
		return Double.parseDouble(s()) ;
	}
}