#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 100000

int H,W;
int POW[21];
int table_index,work_array[20];
int table[100000][20];
int dp[2][100000][2]; //dp[CURRENT,NEXT][直前Wマスの状態][左のマスがJか] = 場合の数
map<int,int> MAP;
char base_map[20][21];

//2進数を10進数に変換する
int calcNUM(int work_array[20]){

	int ret = 0;
	for(int i = W-1; i >= 0; i--){
		ret += work_array[i]*POW[i];
	}

	return ret;
}

int getCode(int work_array[20]){
	return MAP[calcNUM(work_array)];
}

//work_arrayはグローバルに持つ
void makeTable(int index){

	if(index == -1){
		//★新しいものほど右に来る
		for(int i = W-1; i >= 0; i--){
			table[table_index][i] = work_array[i];
		}
		MAP[calcNUM(work_array)] = table_index++;


		return;
	}
	work_array[index] = 0;
	makeTable(index-1);
	if(work_array[index+1] == 0){ //1は連続しない
		work_array[index] = 1;
		makeTable(index-1);
	}
}

//JOIがあるかどうか調べる
bool check_JOI(){

	for(int row = 0; row < H-1; row++){
		for(int col = 0; col < W-1; col++){
			if(base_map[row][col] == 'J' && base_map[row][col+1] == 'O' && base_map[row+1][col] == 'I'){
					return true;
			}
		}
	}
	return false;
}

int main(){

	for(int i = 0; i < 21; i++)POW[i] = pow(2,i);

	scanf("%d %d",&H,&W);

	int space_num = 0;

	for(int row = 0; row < H; row++){
		scanf("%s",base_map[row]);
		for(int col = 0; col < W; col++){
			if(base_map[row][col] == '?')space_num++;
		}
	}

	//3^(空きマス数)を計算
	int ans = 1;
	for(int i = 1; i <= space_num; i++){
		ans *= 3;
		ans %= NUM;
	}

	if(check_JOI()){ //マップにJOIがある場合
		printf("%d\n",ans);
		return 0;
	}

	//2^Wのコード表を作る★桁が大きいほど最近!左にシフトする★
	table_index = 0;
	work_array[W-1] = 0;
	makeTable(W-2);
	work_array[W-1] = 1;
	makeTable(W-2);

	int CURRENT = 0,NEXT = 1;
	for(int state = 0; state < table_index; state++){
		for(int p = 0; p < 2; p++)dp[CURRENT][state][p] = 0;
	}

	int next_state;
	int current_array[20],next_array[20];

	dp[CURRENT][0][false] = 1; //★makeTableの構造により、全0の状態のインデックスは0になるはず★

	//JOI印が発生しない旗の数を数える
	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			//dp[NEXT]を初期化
			for(int state = 0; state < table_index; state++){
				for(int a = 0; a < 2; a++)dp[NEXT][state][a] = 0;
			}

			for(int state = 0; state < table_index; state++){

				for(int i = 0; i < W; i++)current_array[i] = table[state][i];
				for(int i = 1; i < W; i++)next_array[i-1] = table[state][i]; //1つ左にシフト

				for(int a = 0; a < 2; a++){ //直前がJか
					if(dp[CURRENT][state][a] == 0)continue;

					if(base_map[row][col] != '?'){

						switch(base_map[row][col]){
						case 'J':
							next_array[W-1] = 0;
							next_state = getCode(next_array);
							dp[NEXT][next_state][true] += dp[CURRENT][state][a];
							dp[NEXT][next_state][true] %= NUM;
							break;

						case 'O':
							if(a == true){ //1つ前がJ
								if(col != 0){
									next_array[W-1] = 1;

								}else{ //Oが0列目にあるなら、1つ前がJでもフラグを立てない
									next_array[W-1] = 0;
								}
							}else{
								next_array[W-1] = 0;
							}
							next_state = getCode(next_array);
							dp[NEXT][next_state][false] += dp[CURRENT][state][a];
							dp[NEXT][next_state][false] %= NUM;
							break;

						case 'I':
							if(current_array[1] == 1){ //★★JOI印ができてしまう場合
								//Do nothing
							}else{
								next_array[W-1] = 0;
								next_state = getCode(next_array);
								dp[NEXT][next_state][false] += dp[CURRENT][state][a];
								dp[NEXT][next_state][false] %= NUM;
							}
							break;
						}

					}else{ //base_map[row][col] == '?'

						//J
						next_array[W-1] = 0;
						next_state = getCode(next_array);
						dp[NEXT][next_state][true] += dp[CURRENT][state][a];
						dp[NEXT][next_state][true] %= NUM;

						//O
						if(a == true){ //1つ前がJ
							if(col != 0){
								next_array[W-1] = 1;

							}else{ //Oが0列目にあるなら、1つ前がJでもフラグを立てない
								next_array[W-1] = 0;
							}
						}else{
							next_array[W-1] = 0;
						}
						next_state = getCode(next_array);
						dp[NEXT][next_state][false] += dp[CURRENT][state][a];
						dp[NEXT][next_state][false] %= NUM;

						//I
						if(current_array[1] == 1){ //★★JOI印ができてしまう場合
							//Do nothing
						}else{
							next_array[W-1] = 0;
							next_state = getCode(next_array);
							dp[NEXT][next_state][false] += dp[CURRENT][state][a];
							dp[NEXT][next_state][false] %= NUM;
						}
					}
				}
			}
			swap(CURRENT,NEXT);
		}
	}

	int minus = 0;
	for(int state = 0; state < table_index; state++){
		for(int a = 0; a < 2; a++){
			minus += dp[CURRENT][state][a];
			minus %= NUM;
		}
	}

	printf("%d\n",(ans-minus+NUM)%NUM);

	return 0;
}



Measured memory_bytes: 5864