Problem:
JOI 旗 (JOI Flag)
問題
情報オリンピック日本委員会では，今年の日本情報オリンピック (JOI) を宣伝するために， JOI のロゴをモチーフにした旗を作ることになった．旗は「良い旗」でなければならない．「良い旗」とは，アルファベットの J, O, I のいずれかの文字を，縦 M 行，横 N 列の長方形状に並べたもので， J, O, I が以下の図のように (すなわち，J の右隣に O が，その J の下隣に I が) 並んでいる箇所が旗の少なくとも 1 か所にあるものである．
以下の図に，「良い旗」の例を 2 つ示す．
以下の図に，「良い旗」ではない例を 2 つ示す．
いま M, N の値，および旗の一部の場所について J, O, I のどの文字にするかが決まっており，入力としてその情報が与えられる．考えられる「良い旗」は何通りあるかを計算し，その数を 100000 (=10
5
) で割った余りを出力するプログラムを作成せよ．
入力
入力は 1 + M 行からなる．
1 行目には旗の大きさを表す 2 つの整数 M, N (2 ≤ M ≤ 20, 2 ≤ N ≤ 20) が空白で区切られて書かれている．
1 + i 行目 (1 ≤ i ≤ M) には，N 文字からなる文字列が書かれている．各文字は J, O, I, ? のいずれかであり， j 文字目 (1 ≤ j ≤ N) が J, O, I のいずれかである場合は i 行 j 列の場所の文字がそれぞれ J, O, I に決まっていること， ? である場合はまだ決まっていないことを表す．
出力
考えられる「良い旗」の個数を 100000 (=10
5
) で割った余りを 1 行で出力せよ．
入出力例
入力例 1
2 3
??O
IIJ
出力例 1
4
入力例 1 においては，以下の図の 4 通りの「良い旗」が考えられる．
入力例 2
2 2
??
??
出力例 2
3
入力例 3
3 3
??I
???
O?J
出力例 3
53
入力例 4
5 4
JOI?
????
????
????
?JOI
出力例 4
28218
入力例 4 においては，「良い旗」は 2428218 通り考えられるので，それを 100000 (=10
5
) で割った余りである 28218 を出力する．
問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;

#define ALL(a)  a.begin(),a.end()
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))
#define FOR(i, s, e) for (int(i) = (s); (i) < (e); (i)++)
#define debug(x) cerr << #x << ": " << x << endl

using LL = long long; template<class T> using V = vector<T>;

int main() {
	cin.tie(0);
	ios_base::sync_with_stdio(false);

	const LL mod = 100000;
	int W, H; cin >> H >> W;
	V<string>vs(H);
	FOR(i, 0, H) {
		cin >> vs[i];
	}
	V<int>dp(1 << (W - 1), 0);
	dp[0] = 1;
	auto add = [&mod](int &x, int y) {
		x += y;
		x %= mod;
	};
	FOR(i, 0, H) {// 禁止パターンを数え上げる
		FOR(j, 0, W) {
			V<int>nx(1 << (W - 1), 0);
			FOR(state, 0, 1 << (W - 1)) {
				if (dp[state] == 0)continue;
				int ns = state & ~(1 << (j - 1));
				if (vs[i][j] == 'J' || vs[i][j] == '?') {
					if (j < W - 1) {
						add(nx[ns | 1 << j], dp[state]);// jを追加
					}
					else {
						add(nx[ns &~(1 << j)], dp[state]);
					}
				}
				if (vs[i][j] == 'O' || vs[i][j] == '?') {
					add(nx[state&~(1 << j)], dp[state]); // o
				}
				if (vs[i][j] == 'I' || vs[i][j] == '?') { // iをおいては置いてはいけないことはないときに置いてしまっても以降に問題はない
					if (!(state & 1 << j)) {
						add(nx[ns&~(1 << j)], dp[state]);
					}
				}
			}
			dp.swap(nx);
		}
	}
	LL ans = 1;
	FOR(i, 0, H) {
		FOR(j, 0, W) {
			if (vs[i][j] == '?')ans *= 3;
			ans %= mod;
		}
	}
	//debug(ans);
	auto dec = [&mod](LL x, LL y) {
		LL ret = (x - y + mod) % mod;
		return ret >= 0 ? ret : ret + mod;
	};
	FOR(i, 0, 1 << (W - 1)) {
		//cout << dp[i] << endl;
		ans = (dec(ans, dp[i])) % mod;
	}
	cout << ans << endl;


	return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 7200
final_rank: 1

code_snippet: #include<bits/stdc++.h> 
using namespace std;
using ll=long long;

const ll mod=100000;

int main(){
	
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	int N,M;
	cin>>N>>M;
	vector<string> S(N);
	for(int i=0;i<N;i++)cin>>S[i];
	map<pair<ll,ll>,ll> MP;
	ll bmod=(1<<(M-1));
	MP[{0,0}]=1;
	for(int i=0;i<N;i++){
		for(int j=0;j<M;j++){
			map<pair<ll,ll>,ll> NMP;
			for(auto [P,num]:MP){
				if(S[i][j]=='J'||S[i][j]=='?'){
					ll nbit=(P.first*2)%bmod;
					NMP[{nbit,1}]+=num;
					NMP[{nbit,1}]%=mod;
				}
				if(S[i][j]=='O'||S[i][j]=='?'){
					ll nbit=(P.first*2)%bmod;
					if(P.second==1&&j!=0)nbit++;
					NMP[{nbit,0}]+=num;
					NMP[{nbit,0}]%=mod;
				}
				if(S[i][j]=='I'||S[i][j]=='?'){
					if(P.first&(1<<(M-2)))continue;
					ll nbit=(P.first*2)%bmod;
					NMP[{nbit,0}]+=num;
					NMP[{nbit,0}]%=mod;
				}
			}
			swap(MP,NMP);
			
			// for(auto [V,n]:MP){
			// 	cout<<i<<" "<<j<<" "<<V.first<<" "<<V.second<<" "<<n<<endl;
			// }
		}
	}
	ll an=1;
	for(int i=0;i<N;i++){
		for(int j=0;j<M;j++){
			if(S[i][j]=='?')an=(an*3)%mod;
		}
	}
	for(auto [P,n]:MP){
		an-=n;
	}
	an%=mod;
	if(an<0)an+=mod;
	cout<<an%mod<<endl;
}
accuracy: 1
time_ms: 840
memory_kb: 5504
final_rank: 3

code_snippet: #include<bits/stdc++.h>
#define MOD 100000
#define rep(i,n)for(int i=0;i<(n);i++)
using namespace std;

int dp[2][1 << 19];
char s[21][21];
int main() {
	int m, n; scanf("%d%d", &m, &n);
	int cnt = 1;
	rep(i, m)scanf("%s", s[i]);
	rep(i, m)rep(j, n) {
		if (s[i][j] == '?')cnt = (cnt * 3) % MOD;
	}
	int*now = dp[0], *nxt = dp[1];
	now[0] = 1;
	rep(i, m)rep(j, n) {
		fill(nxt, nxt + (1 << n - 1), 0);
		rep(k, 1 << n - 1) {
			if (now[k] == 0)continue;
			int a = k&~(1 << (j - 1));
			if (s[i][j] == 'J' || s[i][j] == '?') {
				if (j < n - 1)(nxt[a | 1 << j] += now[k]) %= MOD;
				else(nxt[a&~(1 << j)] += now[k]) %= MOD;
			}
			if (s[i][j] == 'O' || s[i][j] == '?')
				(nxt[k&~(1 << j)] += now[k]) %= MOD;
			if (s[i][j] == 'I' || s[i][j] == '?') {
				if (!(k >> j & 1))(nxt[a&~(1 << j)] += now[k]) %= MOD;
			}
		}
		swap(now, nxt);
	}
	rep(i, 1 << n - 1)cnt = (cnt + MOD - now[i]) % MOD;
	printf("%d\n", cnt);
}
accuracy: 1
time_ms: 130
memory_kb: 7576
final_rank: 2

code_snippet: #include<iostream>
#include<string>
#include<vector>
using namespace std;
int mod = 100000;
int dp[1 << 20][3], dp_prev[1 << 20][3];
int x[409], H, W; string S;
int power[20];
int main() {
	power[0] = 1; for (int i = 1; i < 20; i++)power[i] = power[i - 1] * 2;
	cin >> H >> W;
	for (int i = 0; i < H; i++) {
		cin >> S;
		for (int j = 0; j < W; j++) {
			if (S[j] == 'J')x[i * W + j] = 1;
			if (S[j] == 'O')x[i * W + j] = 2;
			if (S[j] == 'I')x[i * W + j] = 3;
			if (S[j] == '?')x[i * W + j] = 0;
		}
	}
	if (x[0] == 0 || x[0] == 1)dp_prev[0][1] += 1;
	if (x[0] == 0 || x[0] == 2)dp_prev[0][0] += 1;
	if (x[0] == 0 || x[0] == 3)dp_prev[0][0] += 1;
	for (int i = 1; i < H * W; i++) {
		int mass = i % W;
		for (int j = 0; j < power[W - 1]; j++) {
			int L = 0, R = 0;
			if ((j / power[mass]) % 2 == 1) {
				L = j - power[mass];
				R = L + power[mass - 1];
				if (x[i] == 0 || x[i] == 1) {
					if (mass != W - 1) { dp[L][1] += dp_prev[j][0] + dp_prev[j][1]; dp[L][1] %= mod; }
					if (mass == W - 1) { dp[L][0] += dp_prev[j][0] + dp_prev[j][1]; dp[L][0] %= mod; }
				}
				if (x[i] == 0 || x[i] == 2) {
					dp[L][0] += dp_prev[j][0]; dp[L][0] %= mod;
					dp[R][0] += dp_prev[j][1]; dp[R][0] %= mod;
				}
			}
			else {
				L = j;
				R = j + power[mass - 1];
				if (x[i] == 0 || x[i] == 1) {
					if (mass != W - 1) { dp[L][1] += dp_prev[j][0] + dp_prev[j][1]; dp[L][1] %= mod; }
					if (mass == W - 1) { dp[L][0] += dp_prev[j][0] + dp_prev[j][1]; dp[L][0] %= mod; }
				}
				if (x[i] == 0 || x[i] == 2) {
					dp[L][0] += dp_prev[j][0]; dp[L][0] %= mod;
					dp[R][0] += dp_prev[j][1]; dp[R][0] %= mod;
				}
				if (x[i] == 0 || x[i] == 3) { dp[L][0] += dp_prev[j][0] + dp_prev[j][1]; dp[L][0] %= mod; }
			}
		}
		for (int j = 0; j < power[W - 1]; j++) {
			dp_prev[j][0] = dp[j][0]; dp_prev[j][1] = dp[j][1];
			dp[j][0] = 0; dp[j][1] = 0;
		}
	}
	int C = 1; for (int i = 0; i < H*W; i++) if (x[i] == 0) C = C * 3 % mod;
	int sum = 0; for (int i = 0; i < power[W - 1]; i++) { sum += dp_prev[i][0] + dp_prev[i][1]; sum %= mod; }
	cout << (C + mod - sum) % mod << endl;
	return 0;
}
accuracy: 1
time_ms: 2200
memory_kb: 21860
final_rank: 17

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}
inline double time() {
    return static_cast<long double>(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count()) * 1e-9;
}

constexpr int mod = 100000;
const string joi = "JOI";
int dp[2][1<<19];
int ndp[2][1<<19];

void add(int &x, int y) {
    x += y;
    if (x >= mod) x -= mod;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int h,w; cin >> h >> w;
    vector<string> s(h);
    int res = 1;
    for (int i = 0; i < h; i++) {
        cin >> s[i];
        for (int j = 0; j < w; j++) {
            if (s[i][j] == '?') {
                res *= 3;
                res %= mod;
            }
        }
    }

    dp[0][0] = 1;
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            for (int c = 0; c < 3; c++) {
                if (s[i][j] != '?' and s[i][j] != joi[c]) continue;
                for (int k = 0; k < 2; k++) {
                    for (int l = 0; l < (1<<(w-1)); l++) {
                        if (!dp[k][l]) continue;
                        if (((1<<j)&l) and c == 2) continue;
                        int nk = (c == 0);
                        int ni = i; int nj = j+1;
                        if (nj == w) {
                            ni++; nj = 0;
                        }
                        int nl = l;
                        if ((1<<j)&l) nl -= (1<<j);
                        if (j and k and c == 1) {
                            nl ^= (1<<(j-1));
                        }
                        add(ndp[nk][nl], dp[k][l]);
                    }
                }
            }
            for (int k = 0; k < 2; k++) {
                for (int l = 0; l < (1<<(w-1)); l++) {
                    dp[k][l] = ndp[k][l];
                    ndp[k][l] = 0; 
                }
            }
        }
    }

    for (int k = 0; k < 2; k++) {
        for (int l = 0; l < (1<<(w-1)); l++) {
            add(res, mod-dp[k][l]);
        }
    }

    cout << res << endl;
}
accuracy: 1
time_ms: 610
memory_kb: 11648
final_rank: 4

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <cstring>
using namespace std;


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	const int mod = int(1e5);
	int w = 0;
	int h = 0;
	int dp[2][1 << 20][2];
	string grid[20];
	const char* joi = "JOI";

	cin >> h >> w;
	for (int y = 0; y < h; y++) {
		cin >> grid[y];
	}
	dp[0][0][0] = 1;

	int cur = 0;
	int next = 1;
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			memset(dp[next], 0, sizeof(dp[next]));
			for (int c_state = 0; c_state < 1 << w; c_state++) {
				for(int p = 0; p < 2; p++) {
					if (dp[cur][c_state][p]) {
						for (int k = 0; k < 3; k++) {
							if (grid[y][x] != '?' && grid[y][x] != joi[k]) {
								continue;
							}
							if ((c_state & 1 << x) && k == 2) {
								continue;
							}
							int n_state = c_state & ~(1 << x), np = k == 0;
							if (p && k == 1) {
								n_state |= 1 << (x - 1);
							}
							dp[next][n_state][np] += dp[cur][c_state][p];
							if (dp[next][n_state][np] >= mod) {
								dp[next][n_state][np] -= mod;
							}
						}
					}
				}
			}
			swap(cur, next);
		}
		for (int state = 0; state < 1 << w; state++) {
			dp[cur][state][0] += dp[cur][state][1];
			if (dp[cur][state][0] >= mod) {
				dp[cur][state][0] -= mod;
			}
			dp[cur][state][1] = 0;
		}
	}

	int result = 1;
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			if (grid[y][x] == '?') {
				result = (result * 3) % mod;
			}
		}
	}
	for (int state = 0; state < 1 << w; state++) {
		result = (result + mod - dp[cur][state][0]) % mod;
	}
	cout << result << endl;
	return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 19824
final_rank: 14

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <string.h>
using namespace std;


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	const int mod = int(1e5);
	int w = 0;
	int h = 0;
	int dp[2][1 << 20][2];
	string grid[20];
	const char* joi = "JOI";

	cin >> h >> w;
	for (int y = 0; y < h; y++) {
		cin >> grid[y];
	}
	dp[0][0][0] = 1;

	int cur = 0;
	int next = 1;
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			memset(dp[next], 0, sizeof(dp[next]));
			for (int c_state = 0; c_state < 1 << w; c_state++) {
				for(int p = 0; p < 2; p++) {
					if (dp[cur][c_state][p]) {
						for (int k = 0; k < 3; k++) {
							if (grid[y][x] != '?' && grid[y][x] != joi[k]) {
								continue;
							}
							if ((c_state & 1 << x) && k == 2) {
								continue;
							}
							int n_state = c_state & ~(1 << x), np = k == 0;
							if (p && k == 1) {
								n_state |= 1 << (x - 1);
							}
							dp[next][n_state][np] += dp[cur][c_state][p];
							if (dp[next][n_state][np] >= mod) {
								dp[next][n_state][np] -= mod;
							}
						}
					}
				}
			}
			swap(cur, next);
		}
		for (int state = 0; state < 1 << w; state++) {
			dp[cur][state][0] += dp[cur][state][1];
			if (dp[cur][state][0] >= mod) {
				dp[cur][state][0] -= mod;
			}
			dp[cur][state][1] = 0;
		}
	}

	int result = 1;
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			if (grid[y][x] == '?') {
				result = (result * 3) % mod;
			}
		}
	}
	for (int state = 0; state < 1 << w; state++) {
		result = (result + mod - dp[cur][state][0]) % mod;
	}
	cout << result << endl;
	return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 19824
final_rank: 14

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <string.h>
using namespace std;


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	const int mod = int(1e5);
	int w = 0;
	int h = 0;
	int dp[2][1 << 20][2];
	string grid[20];
	const char* joi = "JOI";

	cin >> h >> w;
	for (int y = 0; y < h; y++) {
		cin >> grid[y];
	}
	dp[0][0][0] = 1;

	int cur = 0;
	int next = 1;
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			memset(dp[next], 0, sizeof(dp[next]));
			for (int c_state = 0; c_state < 1 << w; c_state++) {
				for(int p = 0; p < 2; p++) {
					if (dp[cur][c_state][p]) {
						for (int k = 0; k < 3; k++) {
							if (grid[y][x] != '?' && grid[y][x] != joi[k]) {
								continue;
							}
							if ((c_state & 1 << x) && k == 2) {
								continue;
							}
							int n_state = c_state & ~(1 << x), np = k == 0;
							if (p && k == 1) {
								n_state |= 1 << x - 1;
							}
							dp[next][n_state][np] += dp[cur][c_state][p];
							if (dp[next][n_state][np] >= mod) {
								dp[next][n_state][np] -= mod;
							}
						}
					}
				}
			}
			swap(cur, next);
		}
		for (int state = 0; state < 1 << w; state++) {
			dp[cur][state][0] += dp[cur][state][1];
			if (dp[cur][state][0] >= mod) {
				dp[cur][state][0] -= mod;
			}
			dp[cur][state][1] = 0;
		}
	}

	int result = 1;
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			if (grid[y][x] == '?') {
				result = (result * 3) % mod;
			}
		}
	}
	for (int state = 0; state < 1 << w; state++) {
		result = (result + mod - dp[cur][state][0]) % mod;
	}
	cout << result << endl;
	return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 19816
final_rank: 11

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	const int mod = int(1e5);
	int w = 0;
	int h = 0;
	int dp[2][1 << 20][2];
	string grid[20];
	const char* joi = "JOI";

	cin >> h >> w;
	for (int y = 0; y < h; y++) {
		cin >> grid[y];
	}
	dp[0][0][0] = 1;

	int cur = 0;
	int next = 1;
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			memset(dp[next], 0, sizeof(dp[next]));
			for (int c_state = 0; c_state < 1 << w; c_state++) {
				for(int p = 0; p < 2; p++) {
					if (dp[cur][c_state][p]) {
						for (int k = 0; k < 3; k++) {
							if (grid[y][x] != '?' && grid[y][x] != joi[k]) {
								continue;
							}
							if ((c_state & 1 << x) && k == 2) {
								continue;
							}
							int n_state = c_state & ~(1 << x), np = k == 0;
							if (p && k == 1) {
								n_state |= 1 << x - 1;
							}
							dp[next][n_state][np] += dp[cur][c_state][p];
							if (dp[next][n_state][np] >= mod) {
								dp[next][n_state][np] -= mod;
							}
						}
					}
				}
			}
			swap(cur, next);
		}
		for (int state = 0; state < 1 << w; state++) {
			dp[cur][state][0] += dp[cur][state][1];
			if (dp[cur][state][0] >= mod) {
				dp[cur][state][0] -= mod;
			}
			dp[cur][state][1] = 0;
		}
	}

	int result = 1;
	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			if (grid[y][x] == '?') {
				result = (result * 3) % mod;
			}
		}
	}
	for (int state = 0; state < 1 << w; state++) {
		result = (result + mod - dp[cur][state][0]) % mod;
	}
	cout << result << endl;
	return 0;
}
accuracy: 1
time_ms: 1060
memory_kb: 19748
final_rank: 9

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	const int mod = int(1e5);
	int h = 0;
	int w = 0;
	int dp[2][1 << 20][2];
	string grid[20];
	const char* joi = "JOI";

	cin >> h >> w;
	for (int i = 0; i < h; i++) {
		cin >> grid[i];
	}
	dp[0][0][0] = 1;

	int cur = 0;
	int next = 1;
	for (int i = 0; i < h; i++) {
		for (int j = 0; j < w; j++) {
			memset(dp[next], 0, sizeof(dp[next]));
			for (int bit = 0; bit < 1 << w; bit++) {
				for(int p = 0; p < 2; p++) {
					if (dp[cur][bit][p]) {
						for (int k = 0; k < 3; k++) {
							if (grid[i][j] != '?' && grid[i][j] != joi[k]) {
								continue;
							}
							if ((bit & 1 << j) && k == 2) {
								continue;
							}
							int nbit = bit & ~(1 << j), np = k == 0;
							if (p && k == 1) {
								nbit |= 1 << j - 1;
							}
							dp[next][nbit][np] += dp[cur][bit][p];
							if (dp[next][nbit][np] >= mod) {
								dp[next][nbit][np] -= mod;
							}
						}
					}
				}
			}
			swap(cur, next);
		}
		for (int bit = 0; bit < 1 << w; bit++) {
			dp[cur][bit][0] += dp[cur][bit][1];
			if (dp[cur][bit][0] >= mod) {
				dp[cur][bit][0] -= mod;
			}
			dp[cur][bit][1] = 0;
		}
	}

	int ans = 1;
	for (int i = 0; i < h; i++) {
		for (int j = 0; j < w; j++) {
			if (grid[i][j] == '?') {
				ans = (ans * 3) % mod;
			}
		}
	}
	for (int i = 0; i < 1 << w; i++) {
		ans = (ans + mod - dp[cur][i][0]) % mod;
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 19740
final_rank: 7

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
#define rep(i,b) for(int i = 0; i < (b); i++)


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	const int mod = int(1e5);
	int h = 0;
	int w = 0;
	int dp[2][1 << 20][2];
	string grid[20];
	const char* joi = "JOI";

	cin >> h >> w;
	for (int i = 0; i < h; i++) {
		cin >> grid[i];
	}
	dp[0][0][0] = 1;

	int cur = 0;
	int next = 1;
	for (int i = 0; i < h; i++) {
		for (int j = 0; j < w; j++) {
			memset(dp[next], 0, sizeof(dp[next]));
			for (int bit = 0; bit < 1 << w; bit++) {
				for(int p = 0; p < 2; p++) {
					if (dp[cur][bit][p]) {
						for (int k = 0; k < 3; k++) {
							if (grid[i][j] != '?' && grid[i][j] != joi[k]) {
								continue;
							}
							if ((bit & 1 << j) && k == 2) {
								continue;
							}
							int nbit = bit & ~(1 << j), np = k == 0;
							if (p && k == 1) {
								nbit |= 1 << j - 1;
							}
							dp[next][nbit][np] += dp[cur][bit][p];
							if (dp[next][nbit][np] >= mod) {
								dp[next][nbit][np] -= mod;
							}
						}
					}
				}
			}
			swap(cur, next);
		}
		rep(bit, 1 << w) {
			dp[cur][bit][0] += dp[cur][bit][1];
			if (dp[cur][bit][0] >= mod) {
				dp[cur][bit][0] -= mod;
			}
			dp[cur][bit][1] = 0;
		}
	}

	int ans = 1;
	rep(i, h) {
		rep(j, w) {
			if (grid[i][j] == '?') {
				ans = (ans * 3) % mod;
			}
		}
	}
	rep(i, 1 << w) {
		ans = (ans + mod - dp[cur][i][0]) % mod;
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 19820
final_rank: 12

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
#define rep(i,b) for(int i = 0; i < (b); i++)


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	const int mod = int(1e5);
	int h = 0;
	int w = 0;
	int dp[2][1 << 20][2];
	string grid[20];
	const char* joi = "JOI";

	cin >> h >> w;
	rep(i, h) {
		cin >> grid[i];
	}
	dp[0][0][0] = 1;

	int cur = 0;
	int next = 1;
	rep(i, h) {
		rep(j, w) {
			memset(dp[next], 0, sizeof(dp[next]));
			rep(bit, 1 << w) {
				rep(p, 2) {
					if (dp[cur][bit][p]) {
						rep(k, 3) {
							if (grid[i][j] != '?' && grid[i][j] != joi[k]) {
								continue;
							}
							if ((bit & 1 << j) && k == 2) {
								continue;
							}
							int nbit = bit & ~(1 << j), np = k == 0;
							if (p && k == 1) {
								nbit |= 1 << j - 1;
							}
							dp[next][nbit][np] += dp[cur][bit][p];
							if (dp[next][nbit][np] >= mod) {
								dp[next][nbit][np] -= mod;
							}
						}
					}
				}
			}
			swap(cur, next);
		}
		rep(bit, 1 << w) {
			dp[cur][bit][0] += dp[cur][bit][1];
			if (dp[cur][bit][0] >= mod) {
				dp[cur][bit][0] -= mod;
			}
			dp[cur][bit][1] = 0;
		}
	}

	int ans = 1;
	rep(i, h) {
		rep(j, w) {
			if (grid[i][j] == '?') {
				ans = (ans * 3) % mod;
			}
		}
	}
	rep(i, 1 << w) {
		ans = (ans + mod - dp[cur][i][0]) % mod;
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 19820
final_rank: 12

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
#define rep(i,b) for(int i = 0; i < (b); i++)


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	const int mod = (int)1e5;
	int h = 0;
	int w = 0;
	int dp[2][1 << 20][2];
	string in[20];
	const char* grid = "JOI";

	cin >> h >> w;
	rep(i, h) cin >> in[i];
	dp[0][0][0] = 1;

	int cur = 0, next = 1;
	rep(i, h) {
		rep(j, w) {
			memset(dp[next], 0, sizeof(dp[next]));
			rep(bit, 1 << w) {
				rep(p, 2) {
					if (dp[cur][bit][p]) {
						rep(k, 3) {
							if (in[i][j] != '?' && in[i][j] != grid[k]) {
								continue;
							}
							if ((bit & 1 << j) && k == 2) {
								continue;
							}
							int nbit = bit & ~(1 << j), np = k == 0;
							if (p && k == 1) {
								nbit |= 1 << j - 1;
							}
							dp[next][nbit][np] += dp[cur][bit][p];
							if (dp[next][nbit][np] >= mod) {
								dp[next][nbit][np] -= mod;
							}
						}
					}
				}
			}
			swap(cur, next);
		}
		rep(bit, 1 << w) {
			dp[cur][bit][0] += dp[cur][bit][1];
			if (dp[cur][bit][0] >= mod) {
				dp[cur][bit][0] -= mod;
			}
			dp[cur][bit][1] = 0;
		}
	}

	int ans = 1;
	rep(i, h) {
		rep(j, w) {
			if (in[i][j] == '?') {
				ans = (ans * 3) % mod;
			}
		}
	}
	rep(i, 1 << w) {
		ans = (ans + mod - dp[cur][i][0]) % mod;
	}
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1060
memory_kb: 19752
final_rank: 10

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
#define rep(i,b) for(int i = 0; i < (b); i++)


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	const int mod = (int)1e5;
	int h = 0;
	int w = 0;
	int dp[2][1 << 20][2];
	string in[20];
	const char* grid = "JOI";

	cin >> h >> w;
	rep(i, h) cin >> in[i];
	dp[0][0][0] = 1;

	int cur = 0, next = 1;
	rep(i, h) {
		rep(j, w) {
			memset(dp[next], 0, sizeof(dp[next]));
			rep(bit, 1 << w) {
				rep(p, 2) {
					if (dp[cur][bit][p]) {
						rep(k, 3) {
							if (in[i][j] != '?' && in[i][j] != grid[k]) continue;
							if ((bit & 1 << j) && k == 2) continue;
							int nbit = bit & ~(1 << j), np = k == 0;
							if (p && k == 1) nbit |= 1 << j - 1;
							dp[next][nbit][np] += dp[cur][bit][p];
							if (dp[next][nbit][np] >= mod) dp[next][nbit][np] -= mod;
						}
					}
				}
			}
			swap(cur, next);
		}
		rep(bit, 1 << w) {
			dp[cur][bit][0] += dp[cur][bit][1];
			if (dp[cur][bit][0] >= mod) dp[cur][bit][0] -= mod;
			dp[cur][bit][1] = 0;
		}
	}

	int ans = 1;
	rep(i, h) rep(j, w) if (in[i][j] == '?') ans = (ans * 3) % mod;
	rep(i, 1 << w) ans = (ans + mod - dp[cur][i][0]) % mod;
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 19724
final_rank: 6

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
#define rep(i,b) for(int i = 0; i < (b); i++)


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
	const int mod = (int)1e5;
	int h = 0;
	int w = 0;
	int dp[2][1 << 20][2];
	string in[20];
	const char* grid = "JOI";

	cin >> h >> w;
	rep(i, h) cin >> in[i];
	dp[0][0][0] = 1;

	int cur = 0, next = 1;
	rep(i, h) {
		rep(j, w) {
			memset(dp[next], 0, sizeof(dp[next]));
			rep(bit, 1 << w) rep(p, 2) if (dp[cur][bit][p]) {
				rep(k, 3) {
					if (in[i][j] != '?' && in[i][j] != grid[k]) continue;
					if ((bit & 1 << j) && k == 2) continue;
					int nbit = bit & ~(1 << j), np = k == 0;
					if (p && k == 1) nbit |= 1 << j - 1;
					dp[next][nbit][np] += dp[cur][bit][p];
					if (dp[next][nbit][np] >= mod) dp[next][nbit][np] -= mod;
				}
			}
			swap(cur, next);
		}
		rep(bit, 1 << w) {
			dp[cur][bit][0] += dp[cur][bit][1];
			if (dp[cur][bit][0] >= mod) dp[cur][bit][0] -= mod;
			dp[cur][bit][1] = 0;
		}
	}

	int ans = 1;
	rep(i, h) rep(j, w) if (in[i][j] == '?') ans = (ans * 3) % mod;
	rep(i, 1 << w) ans = (ans + mod - dp[cur][i][0]) % mod;
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 1050
memory_kb: 19788
final_rank: 8

code_snippet: #define READ_FROM_FILE 0

#if READ_FROM_FILE
#include <fstream>
#endif

#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
#define rep(i,b) for(int i = 0; i < (b); i++)


int main() {
#if READ_FROM_FILE
	ifstream ifs("test0.txt");
	cin.rdbuf(ifs.rdbuf());
#endif
const int mod = (int)1e5;
int h, w, dp[2][1<<20][2];
string in[20];
const char *flag = "JOI";
	cin >> h >> w;
	rep(i, h) cin >> in[i];
	dp[0][0][0] = 1;
	int cur = 0, next = 1;
	rep(i, h){
		rep(j, w){
			memset(dp[next], 0, sizeof(dp[next]));
			rep(bit, 1 << w) rep(p, 2) if(dp[cur][bit][p]){
				rep(k, 3){
					if(in[i][j] != '?' && in[i][j] != flag[k]) continue;
					if((bit & 1 << j) && k == 2) continue;
					int nbit = bit & ~(1 << j), np = k == 0;
					if(p && k == 1) nbit |= 1 << j - 1;
					dp[next][nbit][np] += dp[cur][bit][p];
					if(dp[next][nbit][np] >= mod) dp[next][nbit][np] -= mod;
				}
			}
			swap(cur, next);
		}
		rep(bit, 1 << w){
			dp[cur][bit][0] += dp[cur][bit][1];
			if(dp[cur][bit][0] >= mod) dp[cur][bit][0] -= mod;
			dp[cur][bit][1] = 0;
		}
	}
	
	int ans = 1;
	rep(i, h) rep(j, w) if(in[i][j] == '?') ans = (ans * 3) % mod;
	rep(i, 1 << w) ans = (ans + mod - dp[cur][i][0]) % mod;
	cout << ans << endl;
	return 0;
}
accuracy: 1
time_ms: 970
memory_kb: 19816
final_rank: 5

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n - 1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n - i64(1))); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define Bit(n) (1LL << (n))

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    for (std::size_t i = 0; i < vec.size(); i++)
        os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

using std::size_t;
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;

template <class T, T init>
auto make_vector(int n) {
    return std::vector<T>(n, init);
}

template <class T, T init, typename Head, typename... Tail>
auto make_vector(Head n, Tail... ts) {
    return std::vector(n, make_vector<T, init>(ts...));
}

template <class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T>
T mod_pow(T x, i64 n, i64 mod) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

template <class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T>
struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

}  // namespace ebi

namespace ebi {

void main_() {
    const i64 mod = 100000;
    int m,n;
    std::cin >> m >> n;
    std::vector<std::string> s(m);
    std::cin >> s;
    std::vector<i64> dp(1<<n, 0);
    dp[0] = 1;
    std::string joi = "JOI";
    const int BIT = (1<<n) - 1;
    i64 cnt = 0;
    rep(i,0,m) {
        rep(j,0,n) {
            if(s[i][j] == '?') cnt++;
            std::vector<i64> nxt(1<<n, 0);
            std::vector<int> used;
            rep(k,0,3) {
                if(joi[k] == s[i][j] || s[i][j] == '?') {
                    used.emplace_back(k);
                }
            }
            rep(bit, 0, 1<<n) {
                for(auto use: used) {
                    if(((bit >> j) & 1) && use == 2) continue;
                    int nbit = bit & (BIT ^ (1<<j));
                    if(j > 0) nbit &= (BIT ^ (1<<(j-1)));
                    if(use == 0) {
                        if(j != n-1) nbit |= (1<<j);
                        nxt[nbit] += dp[bit];
                    }
                    else if(use == 1) {
                        if(j > 0 && ((bit >> (j-1)) & 1)) nbit |= (1<<(j-1));
                        nxt[nbit] += dp[bit];
                    }
                    else if(use == 2) {
                        if((bit >> j) & 1) continue;
                        assert(!((nbit >> j) & 1));
                        nxt[nbit] += dp[bit];
                    }
                    else {
                        assert(0);
                    }
                    nxt[nbit] %= mod;
                }
            }
            dp = nxt;
        }
    }
    i64 ans = mod_pow(i64(3), cnt, mod);
    rep(bit,0,1<<n) {
        ans -= dp[bit];
        ans = (ans + mod) % mod;
    }
    std::cout << ans << '\n';
}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 3330
memory_kb: 19560
final_rank: 18

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-12;

int N, M, K, H, W, L, R;
//long long int N, M, K, H, W, L, R;

int dp[3][1 << 19][2][2];

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> H >> W;
	vector<string>s(H);
	for (auto &i : s)cin >> i;
	for (int i = 0; i < 1 << W; i++) {
		bool flag = true;
		int by = 1;
		for (int j = 0; j < W; j++) {
			if ((i >> j) & 1) {
				if (s.back()[j] == 'J' || s.back()[j] == 'O')flag = false;
			}
			else {
				if (s.back()[j] == 'I')flag = false;
				if (s.back()[j] == '?') {
					by *= 2;
					by %= 100000;
				}
			}
		}
		if (!flag)continue;
		if (s[H - 2][W - 1] == 'J' || s[H - 2][W - 1] == '?')dp[2][i&((1 << (W - 1)) - 1)][0][0] += by;
		if (s[H - 2][W - 1] == 'O' || s[H - 2][W - 1] == '?')dp[2][i&((1 << (W - 1)) - 1)][1][0] += by;
		if (s[H - 2][W - 1] == 'I' || s[H - 2][W - 1] == '?')dp[2][i&((1 << (W - 1)) - 1)][0][0] += by;
	}
	for (int h = H - 2; h >= 0; h--) {
		for (int w = W - 1; w >= 0; w--) {
			if (h + w == H + W - 3)continue;
			int cw = w & 1;
			if (w == W - 1)cw = 2;
			int befw = (w + 1) & 1;
			if (w + 1 == W - 1)befw = 2;
			if (w == W - 1)befw = 0;
			for (int i = 0; i < 1 << (W - 1); i++) {
				for (int j = 0; j < 2; j++) {
					for (int k = 0; k < 2; k++) {
						dp[cw][i][j][k] = 0;
						dp[befw][i][j][k] %= 100000;
					}
				}
			}
			for (int bit = 0; bit < 1 << (W - 1); bit++) {
				for (int o = 0; o < 2; o++) {
					for (int cnt = 0; cnt < 2; cnt++) {
						if (w == W - 1) {
							if (s[h][w] == 'J' || s[h][w] == '?') {
								int nxbit = bit;
								int nxo = 0;
								int nxcnt = cnt;
								dp[cw][nxbit][nxo][nxcnt] += dp[0][bit][o][cnt];
							}
							if (s[h][w] == 'O' || s[h][w] == '?') {
								int nxbit = bit;
								int nxo = 1;
								int nxcnt = cnt;
								dp[cw][nxbit][nxo][nxcnt] += dp[0][bit][o][cnt];
							}
							if (s[h][w] == 'I' || s[h][w] == '?') {
								int nxbit = bit;
								int nxo = 0;
								int nxcnt = cnt;
								dp[cw][nxbit][nxo][nxcnt] += dp[0][bit][o][cnt];
							}
						}
						else {
							if (s[h][w] == 'J' || s[h][w] == '?') {
								int nxbit = bit;
								if ((bit >> w) & 1)nxbit ^= 1 << w;
								int nxo = 0;
								int nxcnt = cnt || (o && ((bit >> w) & 1));
								dp[cw][nxbit][nxo][nxcnt] += dp[befw][bit][o][cnt];
							}
							if (s[h][w] == 'O' || s[h][w] == '?') {
								int nxbit = bit;
								if ((bit >> w) & 1)nxbit ^= 1 << w;
								int nxo = 1;
								int nxcnt = cnt;
								dp[cw][nxbit][nxo][nxcnt] += dp[befw][bit][o][cnt];
							}
							if (s[h][w] == 'I' || s[h][w] == '?') {
								int nxbit = bit;
								nxbit |= 1 << w;
								int nxo = 0;
								int nxcnt = cnt;
								dp[cw][nxbit][nxo][nxcnt] += dp[befw][bit][o][cnt];
							}
						}
					}
				}
			}
		}
	}
	int ans = 0;
	for (int i = 0; i < 1 << (W - 1); i++) {
		for (int j = 0; j < 2; j++) {
			ans += dp[0][i][j][1];
			ans %= 100000;
		}
	}
	cout << ans << endl;
}
accuracy: 1
time_ms: 5560
memory_kb: 27724
final_rank: 20

code_snippet: #pragma GCC target ("avx")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define _USE_MATH_DEFINES
#include<iostream>
#include<string>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<list>
#include<iomanip>
#include<vector>
#include<random>
#include<functional>
#include<algorithm>
#include<stack>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<unordered_map>
#include<climits>
#include<fstream>
#include<complex>
#include<time.h>
#include<cassert>
#include<functional>
#include<numeric>
#include<tuple>
using namespace std;
using ll = long long;
using ld = long double;
//#define int long long
#define all(a) (a).begin(),(a).end()
#define fs first
#define sc second
#define xx first
#define yy second.first
#define zz second.second
#define C complex<ld>
#define H pair<int, int>
#define P pair<int, pair<int, int>>
#define Q(i,j,k) mkp(i,mkp(j,k))
#define rng(i,s,n) for(int i = (s) ; i < (n) ; i++)
#define rep(i,n) rng(i, 0, (n))
#define mkp make_pair
#define vec vector
#define vi vec<int>
#define pb emplace_back
#define siz(a) (int)(a).size()
#define crdcomp(b) sort(all((b)));(b).erase(unique(all((b))),(b).end())
#define getidx(b,i) lower_bound(all(b),(i))-b.begin()
#define ssp(i,n) (i==(int)(n)-1?"\n":" ")
#define ctoi(c) (int)(c-'0')
#define itoc(c) (char)(c+'0')
#define cyes printf("Yes\n")
#define cno printf("No\n")
#define cdf(n) int quetimes_=(n);rep(qq123_,quetimes_)
#define gcj printf("Case #%lld: ",qq123_+1)
#define readv(a,n) a.resize(n,0);rep(i,(n)) a[i]=read()
//#define endl "\n"
constexpr int mod = 1e9 + 7;
constexpr int Mod = 998244353;
constexpr ld EPS = 1e-10;
constexpr ll inf = 3 * 1e18;
constexpr int Inf = 15 * 1e8;
constexpr int dx[] = { -1,1,0,0 }, dy[] = { 0,0,-1,1 };
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
ll read() { ll u, k = scanf("%lld", &u); return u; }
string reads() { string s; cin >> s; return s; }
H readh(bool g = 0) { H u; int k = scanf("%lld %lld", &u.fs, &u.sc); if (g) u.fs--, u.sc--; return u; }
bool ina(H t, int h, int w) { return 0 <= t.fs && t.fs < h && 0 <= t.sc && t.sc < w; }
bool ina(int t, int l, int r) { return l <= t && t < r; }
ll gcd(ll i, ll j) { return j ? gcd(j, i % j) : i; }
ll popcount(ll x) {
	int sum = 0; for (int i = 0; i < 60; i++)if ((1ll << i) & x) sum++;
	return sum;
}
class mint {
public:long long v;
	  mint(long long v = 0) { s(v % mod); }
	  constexpr static int mod = 1e5;
	  constexpr static int fn_ = 500005;
	  static mint fact[fn_], comp[fn_];
	  mint pow(mint x) const {
		  mint b(v), c(1);
		  while (x.v) {
			  if (x.v & 1) c *= b;
			  b *= b;
			  x.v >>= 1;
		  }
		  return c;
	  }
	  inline mint& s(int vv) {
		  v = vv < mod ? vv : vv - mod;
		  return *this;
	  }
	  inline mint inv()const { return pow(mod - 2); }
	  inline mint operator-()const { return mint() - *this; }
	  inline mint& operator+=(const mint b) { return s(v + b.v); }
	  inline mint& operator-=(const mint b) { return s(v + mod - b.v); }
	  inline mint& operator*=(const mint b) { v = v * b.v % mod; return *this; }
	  inline mint& operator/=(const mint b) { return (*this) *= b.inv(); }
	  inline mint operator+(const mint b) const { return mint(v) += b; }
	  inline mint operator-(const mint b) const { return mint(v) -= b; }
	  inline mint operator*(const mint b) const { return mint(v) *= b; }
	  inline mint operator/(const mint b) const { return mint(v) /= b; }
	  friend ostream& operator<<(ostream& os, const mint& m) {
		  return os << m.v;
	  }
	  friend istream& operator>>(istream& is, mint& m) {
		  int x; is >> x; m = mint(x);
		  return is;
	  }
	  bool operator<(const mint& r)const { return v < r.v; }
	  bool operator>(const mint& r)const { return v > r.v; }
	  bool operator<=(const mint& r)const { return v <= r.v; }
	  bool operator>=(const mint& r)const { return v >= r.v; }
	  bool operator==(const mint& r)const { return v == r.v; }
	  bool operator!=(const mint& r)const { return v != r.v; }
	  explicit operator bool()const { return v; }
	  explicit operator int()const { return v; }
	  mint comb(mint k) {
		  if (k > * this) return mint();
		  if (!fact[0]) combinit();
		  if (v >= fn_) {
			  if (k > * this - k) k = *this - k;
			  mint tmp(1);
			  for (int i = v; i >= v - k.v + 1; i--) tmp *= mint(i);
			  return tmp * comp[k.v];
		  }
		  else return fact[v] * comp[k.v] * comp[v - k.v];
	  }//nCk
	  static void combinit() {
		  fact[0] = 1;
		  for (int i = 1; i < fn_; i++) fact[i] = fact[i - 1] * mint(i);
		  comp[fn_ - 1] = fact[fn_ - 1].inv();
		  for (int i = fn_ - 2; i >= 0; i--) comp[i] = comp[i + 1] * mint(i + 1);
	  }
}; mint mint::fact[fn_], mint::comp[fn_];
//--------------------------------------------------------------
int h, w;
string s[30];

signed main() {
	cin >> h >> w;
	rep(i, h) cin >> s[i];


	mint ans = 1;
	rep(i, h)rep(j, w)if (s[i][j] == '?') ans *= 3;

	vec<mint>dp(1 << w, 0);
	dp[0] = 1;


	rep(i, h)rep(j, w) {

		vec<mint>dp2(1 << w, 0);

		auto F = [&](int k) ->int{
			return (k & ~(1 << (w - 1)));
		};

		if (s[i][j] == 'J'||s[i][j]=='?') {
			rep(k, 1 << w) {
				dp2[(F(k) >> 1) | (1 << (w - 1))] += dp[k];
			}
		}

		if (s[i][j] == 'O' || s[i][j] == '?') {
			rep(k, 1 << w) {
				if (j > 0) dp2[k >> 1] += dp[k];
				else dp2[F(k) >> 1] += dp[k];
			}
		}

		if (s[i][j] == 'I' || s[i][j] == '?') {
			rep(k, 1 << w) {
				if (k & 1) continue;
				dp2[F(k) >> 1] += dp[k];
			}
		}
		swap(dp, dp2);
	}
	rep(i, 1 << w) ans -= dp[i];
	cout << ans << endl;
}
accuracy: 1
time_ms: 2010
memory_kb: 27200
final_rank: 19

code_snippet: #include <iostream>
#include <numeric>
#include <vector>

template <class T>
std::vector<T> vec(int len, T elem) { return std::vector<T>(len, elem); }

constexpr int MOD = 100000;

void solve() {
    int h, w;
    std::cin >> h >> w;

    int tot = 1;
    const int mask = (1 << (w - 1)) - 1;
    auto dp = vec(3, vec(1 << (w - 1), 0));
    dp[0][0] = 1;
    auto ndp = dp;

    for (int i = 0; i < h; ++i) {
        for (int j = 0; j < w; ++j) {
            for (auto& v : ndp) std::fill(v.begin(), v.end(), 0);

            int id;
            {
                char c;
                std::cin >> c;
                for (id = 0; id < 3; ++id) {
                    if (c == "JOI"[id]) break;
                }
            }

            if (id == 3) (tot *= 3) %= MOD;

            for (int p = 0; p < 3; ++p) {
                for (int k = 0; k < 3; ++k) {
                    if (id != 3 && k != id) continue;

                    for (int b = 0; b < (1 << (w - 1)); ++b) {
                        if (k == 2 && ((b >> (w - 2)) & 1)) continue;

                        int nb = ((b << 1) & mask) + (p == 0 && k == 1 && j != 0);
                        ndp[k][nb] += dp[p][b];
                        if (ndp[k][nb] >= MOD) ndp[k][nb] -= MOD;
                    }
                }
            }
            std::swap(dp, ndp);
        }
    }

    int out = 0;
    for (const auto& v : dp) {
        for (const auto& x : v) {
            out += x;
            if (out >= MOD) out -= MOD;
        }
    }

    std::cout << (tot - out + MOD) % MOD << "\n";
}

int main() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);

    solve();

    return 0;
}
accuracy: 1
time_ms: 3810
memory_kb: 15132
final_rank: 16