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:
#include<bits/stdc++.h>
using namespace std;
 
#define MOD 998244353
template<typename ty1,typename ty2>
inline int add(ty1 x, ty2 y) {
	if(y>=MOD)y%=MOD;
	if(x>=MOD)x%=MOD;
    x += y; return x < MOD ? x : x - MOD;
}
template<typename ty1,typename ty2>
inline void addto(ty1 &x, ty2 y) {
		  if(y>=MOD)y%=MOD;
		  if(x>=MOD)x%=MOD;
	      x += y; if (x >= MOD) x -= MOD;
}
template<typename ty1,typename ty2>
inline int sub(ty1 x, ty2 y) {
		if(y>=MOD)y%=MOD;
		 if(x>=MOD)x%=MOD;
        x -= y; return x < 0 ? x + MOD : x;
}
template<typename ty1,typename ty2>
inline void subto(ty1 &x, ty2 y) {
	if(y>=MOD)y%=MOD;
	if(x>=MOD)x%=MOD;
    x -= y; if (x < 0) x += MOD;
}
template<typename ty1,typename ty2>
inline int mul(ty1 x, ty2 y) {
        if(y>=MOD)y%=MOD;
		if(x>=MOD)x%=MOD;
        return 1ll * x * y % MOD;
}
template<typename ty1,typename ty2>
void multo(ty1 &x, ty2 y) {
        if(y>=MOD)y%=MOD;
		if(x>=MOD)x%=MOD;
        x=1ll * x * y % MOD;
}
  
long long int gcd(long long int a, long long int b){
	if (a > b){
		swap(a, b);
	}
	while (a){
		swap(a, b);
		a %= b;
	}
	return b;
}
long long int lcm(long long int a, long long int b){
	return a / gcd(a, b)*b;
}
long long int ppow(long long int i, long long int j){
		long long int res = 1LL;
		while (j){
			if ((j & 1LL)){
				res *= i;
				if (res >= MOD){
					res %= MOD;
				}
			}
			j >>= 1;
			i *= i;
			if (i >= MOD){
				i %= MOD;
			}
		}
		return res;
	}
class Combination{
	
public:
	vector<long long int> k;
	vector<long long int> r;
	void resize(int N){
		k.resize(N + 2);
		r.resize(N + 2);
		k[0] = 1;
		for (int i = 1; i < N+2; i++){
			k[i] = k[i - 1];
			k[i] *= i;
			if (k[i] >= MOD)k[i] %= MOD;
		}
		long long int al = k[k.size() - 1];
		long long int iv = ppow(k[k.size() - 1],MOD-2);
		r[k.size() - 1] = iv;
		for (int i = (int)(r.size()) - 2; i >= 0; i--){
			r[i] = r[i + 1] * (i + 1);
			if (r[i] >= MOD){
				r[i] %= MOD;
			}
		}
	}
	long long int C(int a, int b){
		if (a < b)return 0;
		long long int up = k[a];
		long long int dw = r[b] * r[a - b];
		dw %= MOD;
		up *= dw;
		up %= MOD;
		return up;
	}
	long long int H(int a, int b){
		return C(a + b - 1, b);
	}
	long long int catalan_number(int n){
		return (C(2 * n, n) + MOD - C(2 * n, n - 1)) % MOD;
	}
};
Combination C;
int h;
int w;
#define MAX 12
char room[MAX][MAX];
bool us[MAX][MAX];
int dp[MAX][MAX];

bool use[MAX][MAX];
int dp2[MAX][MAX];

int dp3[MAX][MAX][2];
void init(){
	dp3[0][0][0]=1;
	dp3[0][0][1]=1;
	for(int i=0;i<=h;i++){
		for(int j=0;j<=w;j++){
			int inv=1;
			for(int go=j+1;go<=w;go++){
				multo(inv,ppow(go-j,MOD-2));
				addto(dp3[i][go][0],mul(inv,dp3[i][j][1]));	
			}
			inv=1;
			for(int go=i+1;go<=h;go++){
				multo(inv,ppow(go-i,MOD-2));
				addto(dp3[go][j][1],mul(inv,dp3[i][j][0]));
			}
		}
	}
}
inline int f(int a,int b){
	if(use[a][b])return dp[a][b];
	if(a==0||b==0){
		//cerr<<"er"<<endl;
		//puts("er");
		return 1;
	}
	use[a][b]=true;
	int ret=add(dp3[a][b][0],dp3[a][b][1]);
	for(int i=1;i<=max(a,b);i++){
		multo(ret,i);
		if(i<=min(a,b)){
			multo(ret,i);
		}
	}
	return dp[a][b]=ret;
}

inline int solve(int a,int b){
	a=h-a;
	b=w-b;
	if(a==0&&b==0){
		//cerr<<"ok4"<<endl;
		return 1;
	}
	if(us[a][b])return dp2[a][b];
	us[a][b]=true;
	if(a==0){
		//cerr<<"OK"<<endl;
		return dp2[a][b]=ppow(2,b);
	}
	if(b==0){
		//cerr<<"OK2"<<endl;
		return dp2[a][b]=ppow(2,a);
	}
	for(int z1=0;z1<=a;z1++){
		for(int z2=0;z2<=b;z2++){
			addto(dp2[a][b],mul(mul(C.C(a,z1),C.C(b,z2)),mul(f(a-z1,b-z2),f(z1,z2))));
		}
	}
	return dp2[a][b];
}


int main(){
	cin>>h>>w;
	C.resize(100);
	init();
	int ans=0;
	for(int i=0;i<h;i++){
		scanf("%s",room[i]);
	}
	for(int i=1;i<(1<<h);i++){
		for(int j=1;j<(1<<w);j++){
			int hh=0;
			int ww=0;
			bool nah=false;
			for(int a=0;a<h;a++){
				if(!((i>>a)&1)){
					continue;
				}
				hh++;
				int tmp=-1;
				ww=0;
				bool ng=false;
				for(int b=0;b<w;b++){
					if(!((j>>b)&1)){
						continue;
					}
					ww++;
					int col=(room[a][b]=='.');
					if(tmp==-1)tmp=col;
					if(tmp!=col){
						ng=true;
					}
				}
				if(ng==false){
					nah=true;
				}
			}
			for(int b=0;b<w;b++){
				if(!((j>>b)&1)){
					continue;
				}
				int tmp=-1;
				bool ng=false;
				for(int a=0;a<h;a++){
					if(!((i>>a)&1)){
						continue;
					}
					int col=(room[a][b]=='.');
					if(tmp==-1)tmp=col;
					if(tmp!=col){
						ng=true;
					}
				}
				if(ng==false){
					nah=true;
				}
			}
			if(nah)continue;
			//cerr<<hh<<" "<<ww<<" "<<solve(hh,ww)<<endl;
			addto(ans,solve(hh,ww));
		}
	}
	addto(ans,f(h,w));
	printf("%d\n",ans);
	return 0;
}