#include #include #include #include #include constexpr uint32_t p = 998244353; typedef uint32_t *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, uint32_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(uint32_t hash, int m) { for(int i=0; i> (2*i)) & 3U) == 3U) return false; } return true; } int main() { int n, m; std::cin >> n >> m; int questionmarks = 0; 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; questionmarks++; } } uint32_t mapsize = (1U << (2*m)); flagmap noflags[3]; flagmap newnoflags[3]; for(int i=0; i<3; i++) { noflags[i] = new uint32_t[mapsize]; newnoflags[i] = new uint32_t[mapsize]; } for(int i=0; i<3; i++) { std::memset(noflags[i], 0, mapsize * sizeof(int32_t)); } populateNoFlags(grid, noflags, 0, m, 0); for(int row=1; row> (2*col)) & 3U, (hash >> (2*(col-1))) & 3U, j)) { newnoflags[(hash >> (2*col)) & 3U][newhash | (j << (2*col))] = (newnoflags[(hash >> (2*col)) & 3U][newhash | (j << (2*col))] + noflags[prev][hash]) % p; } } } } } for(int i=0; i<3; i++) { std::swap(noflags[i], newnoflags[i]); } } } uint32_t tot = 1; for(int i=0; i