#include #include #include #include constexpr int64_t p = 998244353; typedef std::unordered_map flagmap; bool isflag(int a, int b, int c, int d) { return a == 0 && b == 1 && c ==2 && d == 1; } void populateNoFlags(const std::vector &grid, flagmap *fm, int cur, int m, uint64_t hash) { if(cur == m) { fm[0][hash] = 1; return; } if(grid[cur] == 3) { for(uint64_t j=0; j<3; j++) { uint64_t newhash = hash; newhash |= (j << (2*cur)); populateNoFlags(grid, fm, cur+1, m, newhash); } } else { hash |= (grid[cur] << (2*cur)); populateNoFlags(grid, fm, cur+1, m, hash); } } int main() { int n, m; std::cin >> n >> m; std::vector grid(n*m); for(int i=0; i> c; if(c == 'I') grid[i] = 0; else if(c == 'C') grid[i] = 1; else if(c == 'P') grid[i] = 2; else grid[i] = 3; } flagmap noflags[3]; flagmap flags[3]; populateNoFlags(grid, noflags, 0, m, 0); for(int row=1; row toprocess; if(grid[row*m] == 3) toprocess = {0ULL, 1ULL, 2ULL}; else toprocess.push_back(grid[row*m]); for(uint64_t j : toprocess) { newnoflags[it.first & 3][newhash | j] = (newnoflags[it.first & 3][newhash | j] + it.second) % p; } } for(auto it : flags[prev]) { uint64_t newhash = it.first; newhash &= ~(3ULL); std::vector toprocess; if(grid[row*m] == 3) toprocess = {0ULL, 1ULL, 2ULL}; else toprocess.push_back(grid[row*m]); for(uint64_t j : toprocess) { newflags[it.first & 3][newhash | j] = (newflags[it.first & 3][newhash | j] + it.second) % p; } } } for(int i=0; i<3; i++) { noflags[i] = newnoflags[i]; flags[i] = newflags[i]; } } for(int col = 1; col < m; col++) { flagmap newnoflags[3]; flagmap newflags[3]; for(int prev=0; prev<3; prev++) { for(auto it : noflags[prev]) { uint64_t newhash = it.first; newhash &= ~(3ULL << (2*col)); std::vector toprocess; if(grid[row*m + col] == 3) toprocess = {0ULL, 1ULL, 2ULL}; else toprocess.push_back(grid[row*m + col]); for(uint64_t j : toprocess) { if(isflag(prev, (it.first >> (2*col)) & 3ULL, (it.first >> (2*(col-1))) & 3ULL, j)) newflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] + it.second) % p; else { newnoflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newnoflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] + it.second) % p; } } } for(auto it : flags[prev]) { uint64_t newhash = it.first; newhash &= ~(3ULL << (2*col)); std::vector toprocess; if(grid[row*m + col] == 3) toprocess = {0ULL, 1ULL, 2ULL}; else toprocess.push_back(grid[row*m + col]); for(uint64_t j : toprocess) { int idx = (it.first >> (2*col)) & 3ULL; newflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newflags[(it.first >> (2*col)) & 3ULL][newhash | (j << (2*col))] + it.second) % p; } } } for(int i=0; i<3; i++) { noflags[i] = newnoflags[i]; flags[i] = newflags[i]; } } } uint64_t finalanswer = 0; for(int j=0; j<3; j++) { for(auto it : flags[j]) { finalanswer = (finalanswer + it.second) % p; } } std::cout << finalanswer << std::endl; }