Problem: We have an H \times W grid, where each square is painted white or black in the initial state. Given are strings A_1, A_2, ..., A_H representing the colors of the squares in the initial state. For each pair (i, j) (1 \leq i \leq H, 1 \leq j \leq W), if the j-th character of A_i is `.`, the square at the i-th row and j-th column is painted white; if that character is `#`, that square is painted black.

Among the 2^{HW} ways for each square in the grid to be painted white or black, how many can be obtained from the initial state by performing the operations below any number of times (possibly zero) in any order? Find this count modulo 998,244,353.

* Choose one row, then paint all the squares in that row white.
* Choose one row, then paint all the squares in that row black.
* Choose one column, then paint all the squares in that column white.
* Choose one column, then paint all the squares in that column black.

Constraints

* 1 \leq H, W \leq 10
* |A_i| = W (1 \leq i \leq H)
* All strings A_i consist of `.` and `#`.
* H and W are integers.

Input

Input is given from Standard Input in the following format:


H W
A_1
A_2
\vdots
A_H


Output

Print the answer.

Examples

Input

2 2
#.
.#


Output

15


Input

2 2
.
.#


Output

15


Input

3 3
...
...
...


Output

230


Input

2 4
...
...#


Output

150


Input

6 7
.......
.......
.#.....
..#....
.#.#...
.......


Output

203949910

Solution (in CPP):

Solution:
// #pragma GCC target("avx")  // CPU 処理並列化
// #pragma GCC optimize("O3")  // CPU 処理並列化
// #pragma GCC optimize("unroll-loops")  // 条件処理の呼び出しを減らす
// #define BEGIN_STACK_EXTEND(size) void * stack_extend_memory_ = malloc(size);void * stack_extend_origin_memory_;char * stack_extend_dummy_memory_ = (char*)alloca((1+(int)(((long long)stack_extend_memory_)&127))*16);*stack_extend_dummy_memory_ = 0;asm volatile("mov %%rsp, %%rbx\nmov %%rax, %%rsp":"=b"(stack_extend_origin_memory_):"a"((char*)stack_extend_memory_+(size)-1024));
// #define END_STACK_EXTEND asm volatile("mov %%rax, %%rsp"::"a"(stack_extend_origin_memory_));free(stack_extend_memory_);

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<deque>
#include<stack>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#include<stdlib.h>
#include<cassert>
#include<time.h>
#include<bitset>
#include<numeric>
#include<unordered_set>
#include<unordered_map>
#include<complex>
using namespace std;
const long long mod=998244353;
const long long inf=mod*mod;
const long long d2=(mod+1)/2;
const long double EPS=1e-9;
const long double INF=1e+10;
const long double PI=acos(-1.0);
const int C_SIZE = 3100000;
const int UF_SIZE = 3100000;
namespace{
	long long fact[C_SIZE];
	long long finv[C_SIZE];
	long long inv[C_SIZE];
	inline long long Comb(int a,int b){
	 	if(a<b||b<0)return 0;
	 	return fact[a]*finv[b]%mod*finv[a-b]%mod;
	}
	void init_C(int n){
		fact[0]=finv[0]=inv[1]=1;
		for(int i=2;i<n;i++){
			inv[i]=(mod-(mod/i)*inv[mod%i]%mod)%mod;
		}
		for(int i=1;i<n;i++){
			fact[i]=fact[i-1]*i%mod;
			finv[i]=finv[i-1]*inv[i]%mod;
		}
	}
	long long pw(long long a,long long b){
		if(a<0LL)return 0;
		if(b<0LL)return 0;
		long long ret=1;
		while(b){
			if(b%2)ret=ret*a%mod;
			a=a*a%mod;
			b/=2;
		}
		return ret;
	}
	long long pw_mod(long long a,long long b,long long M){
		if(a<0LL)return 0;
		if(b<0LL)return 0;
		long long ret=1;
		while(b){
			if(b%2)ret=ret*a%M;
			a=a*a%M;
			b/=2;
		}
		return ret;
	}
	int pw_mod_int(int a,int b,int M){
		if(a<0)return 0;
		if(b<0)return 0;
		int ret=1;
		while(b){
			if(b%2)ret=(long long)ret*a%M;
			a=(long long)a*a%M;
			b/=2;
		}
		return ret;
	}
	int ABS(int a){return max(a,-a);}
	long long ABS(long long a){return max(a,-a);}
	double ABS(double a){return max(a,-a);}
	int sig(double r) { return (r < -EPS) ? -1 : (r > +EPS) ? +1 : 0; }
	int UF[UF_SIZE];
	void init_UF(int n){
		for(int i=0;i<n;i++)UF[i]=-1;
	}
	int FIND(int a){
		if(UF[a]<0)return a;
		return UF[a]=FIND(UF[a]);
	}
	void UNION(int a,int b){
		a=FIND(a);b=FIND(b);if(a==b)return;
		// if(UF[a]>UF[b])swap(a,b);
		UF[a]+=UF[b];UF[b]=a;
	}
}
// ここから編集しろ
char in[12][12];
long long P[12][12];
long long dp[2][12][12];
long long f(int a,int b){
	if(a+b==0)return 1;
	for(int i=0;i<2;i++)for(int j=0;j<12;j++)for(int k=0;k<12;k++)dp[i][j][k]=0;
	dp[0][0][0]=dp[1][0][0]=1;
	for(int i=0;i<=a;i++){
		for(int j=0;j<=b;j++){
			for(int k=0;k<2;k++){
				if(!dp[k][i][j])continue;
				if(k==0){
					for(int l=1;i+l<=a;l++){
						dp[!k][i+l][j]=(dp[!k][i+l][j]+dp[k][i][j]*Comb(a-i,l))%mod;
					}
				}else{
					for(int l=1;j+l<=b;l++){
						dp[!k][i][j+l]=(dp[!k][i][j+l]+dp[k][i][j]*Comb(b-j,l))%mod;
					}
				}
			}
		}
	}
	return (dp[0][a][b]+dp[1][a][b])%mod;
}
int main(){
	int a,b;scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++)scanf("%s",in[i]);
	init_C(100);
	for(int i=0;i<=a;i++){
		for(int j=0;j<=b;j++){
			P[i][j]=f(i,j);
		}
	}
	long long ret=0;
	for(int i=0;i<(1<<a);i++){
		for(int j=0;j<(1<<b);j++){
			bool ok=true;
			int N=a;
			int M=b;
			for(int k=0;k<a;k++){
				if(!(i&(1<<k)))continue;
				N--;
				int A=0;
				int B=0;
				for(int l=0;l<b;l++){
					if(!(j&(1<<l)))continue;
					if(in[k][l]=='#')A++;
					else B++;
				}
				if((A==0||B==0)){
					ok=false;break;
				}
			}
			if(!ok){
				continue;
			}
			for(int k=0;k<b;k++){
				if(!(j&(1<<k)))continue;
				M--;
				int A=0;
				int B=0;
				for(int l=0;l<a;l++){
					if(!(i&(1<<l)))continue;
					if(in[l][k]=='#')A++;
					else B++;
				}
				if((A==0||B==0)){
					ok=false;break;
				}
			}
			if(!ok){
				continue;
			}
			if(N==a&&M==b){
				ret=(ret+P[a][b])%mod;
			}else{
				for(int k=0;k<=N;k++){
					for(int l=0;l<=M;l++){
						long long ks=Comb(N,k)*Comb(M,l)%mod;
						ks=ks*P[k][l]%mod;
						ks=ks*P[N-k][M-l]%mod;
						ret=(ret+ks)%mod;
					}
				}
			}
			// printf("%d %d: %lld\n",i,j,ret);
		}
	}
	printf("%lld\n",ret);
}