#include #include #include #include constexpr int64_t p = 998244353; typedef std::vector 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); } } bool validHash(uint64_t hash, int m) { for(int i=0; i> (2*i)) & 3ULL) == 3ULL) return false; } return true; } 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; } int64_t mapsize = (1LL << (2*m)); flagmap noflags[3]; flagmap flags[3]; for(int i=0; i<3; i++) { noflags[i].resize(mapsize); flags[i].resize(mapsize); } 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[hash & 3][newhash | j] = (newnoflags[hash & 3][newhash | j] + noflags[prev][hash]) % p; newflags[hash & 3][newhash | j] = (newflags[hash & 3][newhash | j] + flags[prev][hash]) % 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 i=0; i<3; i++) { newnoflags[i].resize(mapsize); newflags[i].resize(mapsize); } for(int prev=0; prev<3; prev++) { for(int64_t hash = 0; hash < mapsize; hash++) { if(!validHash(hash, m)) continue; uint64_t newhash = hash; 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, (hash >> (2*col)) & 3ULL, (hash >> (2*(col-1))) & 3ULL, j)) newflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] + noflags[prev][hash]) % p; else { newnoflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newnoflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] + noflags[prev][hash]) % p; } newflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] = (newflags[(hash >> (2*col)) & 3ULL][newhash | (j << (2*col))] + flags[prev][hash]) % 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(int64_t hash = 0; hash < mapsize; hash++) { finalanswer = (finalanswer + flags[j][hash]) % p; } } std::cout << finalanswer << std::endl; }