#include #include #include #include #include #include constexpr int64_t MOD = 998244353; constexpr int64_t I_CELL = 0x0; constexpr int64_t C_CELL = 0x1; constexpr int64_t P_CELL = 0x2; template T& inc(T& a, T b) { a += b; if (a >= MOD) a -= MOD; return a; } int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr); int32_t n, m; std::cin >> n >> m; std::string s; { std::string row; for (auto i = 0; i < n; ++i) { std::cin >> row; s += row; } } std::vector rem(n * m); rem.back() = 1; for (int32_t idx = n * m - 1; idx > 0; --idx) { rem[idx - 1] = rem[idx] * (s[idx] == '?' ? 3 : 1) % MOD; } const int64_t mask = (1 << (2 * m + 2)) - 1; auto nxt = [&mask](int64_t state, int64_t c) -> int64_t { return (state << 2 | c) & mask; }; std::array, 2> dp{}; dp[0].assign(mask + 1, 0); dp[0][0] = 1; int64_t ways = 0; for (int64_t idx = 0; idx < n * m; ++idx) { dp[1].assign(mask + 1, 0); int64_t r = idx / m; int64_t c = idx % m; for (auto state = 0; state < dp[0].size(); ++state) { auto freq = dp[0][state]; if (!freq) continue; bool finishes = r > 0 && c > 0; if (finishes) { int64_t topLeft = (state >> (2 * m)) & 0x3; int64_t top = (state >> (2 * m - 2)) & 0x3; int64_t before = state & 0x3; if (!(topLeft == I_CELL && top == C_CELL && before == P_CELL)) { finishes = false; } } if (s[idx] == 'I' || s[idx] == '?') { inc(dp[1][nxt(state, I_CELL)], freq); } if (s[idx] == 'C' || s[idx] == '?') { if (finishes) { inc(ways, freq * rem[idx] % MOD); } else { inc(dp[1][nxt(state, C_CELL)], freq); } } if (s[idx] == 'P' || s[idx] == '?') { inc(dp[1][nxt(state, P_CELL)], freq); } } dp[0] = std::move(dp[1]); } std::cout << ways << '\n'; return 0; }