Problem p00482 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <map>
#include <string>

using namespace std;

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define REP(i, n) FOR(i, 0, n)
#define MOD 100000

int m, n;
string str[20];
map<int, int> comp;
int dp[2][20][11000][2];
int cnt[20][20];

int mod_pow(int x, int n) {
  if (n == 0)
    return 1;
  int res = mod_pow((long long)x * x % MOD, n / 2);
  if (n & 1)
    res = (long long)res * x % MOD;

  return res;
}

int main() {
  cin >> m >> n;
  REP(i, m) cin >> str[i];

  for (int i = m * n - 2; i >= 0; i--)
    cnt[i / n][i % n] =
        cnt[(i + 1) / n][(i + 1) % n] + (str[(i + 1) / n][(i + 1) % n] == '?');
  REP(i, m) REP(j, n) cnt[i][j] = mod_pow(3, cnt[i][j]);

  int c = 0;
  REP(i, 1 << n - 1) {
    bool f = false;
    REP(j, n - 2) if ((i >> j & 1) && (i >> (j + 1) & 1)) f = true;
    if (f)
      continue;
    comp[i] = c++;
  }

  for (int i = m - 1; i >= 0; i--) {
    for (int j = n - 1; j >= 0; j--) {
      for (map<int, int>::iterator it = comp.begin(); it != comp.end(); it++) {
        int s = it->first;

        REP(l, 2) {
          int tmp = 0;

          int nexts = comp[s >> 1];

          if (str[i][j] == 'J' || str[i][j] == '?') {
            if (j == n - 1)
              tmp += dp[(i + 1) % 2][0][nexts][0];
            else
              tmp += dp[i % 2][j + 1][nexts][1];
          }

          if (str[i][j] == 'O' || str[i][j] == '?') {
            if (l) {
              if (comp.find((s >> 1) | (1 << n - 2)) != comp.end()) {
                if (j == n - 1)
                  tmp += dp[(i + 1) % 2][0][comp[(s >> 1) | (1 << (n - 2))]][0];
                else
                  tmp += dp[i % 2][j + 1][comp[(s >> 1) | (1 << (n - 2))]][0];
              }
            } else {
              if (j == n - 1)
                tmp += dp[(i + 1) % 2][0][nexts][0];
              else
                tmp += dp[i % 2][j + 1][nexts][0];
            }
          }

          if (str[i][j] == 'I' || str[i][j] == '?') {
            if (s & 1) {
              tmp += cnt[i][j];
            } else {
              if (j == n - 1)
                tmp += dp[(i + 1) % 2][0][nexts][0];
              else
                tmp += dp[i % 2][j + 1][nexts][0];
            }
          }

          dp[i % 2][j][comp[s]][l] = tmp % MOD;
        }
      }
    }
  }

  cout << dp[0][0][comp[0]][0] << endl;

  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <string>

using namespace std;

#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define REP(i, n) FOR(i, 0, n)
#define MOD 100000

int m, n;
string str[20];
int dp[2][20][1 << 19][2];
int cnt[20][20];

int mod_pow(int x, int n) {
  if (n == 0)
    return 1;
  int res = mod_pow((long long)x * x % MOD, n / 2);
  if (n & 1)
    res = (long long)res * x % MOD;

  return res;
}

int main() {
  cin >> m >> n;
  REP(i, m) cin >> str[i];

  for (int i = m * n - 2; i >= 0; i--)
    cnt[i / n][i % n] =
        cnt[(i + 1) / n][(i + 1) % n] + (str[(i + 1) / n][(i + 1) % n] == '?');
  REP(i, m) REP(j, n) cnt[i][j] = mod_pow(3, cnt[i][j]);

  for (int i = m - 1; i >= 0; i--) {
    for (int j = n - 1; j >= 0; j--) {
      REP(k, 1 << (n - 1)) {
        REP(l, 2) {
          int tmp = 0;
          int nexts = k >> 1;

          if (str[i][j] == 'J' || str[i][j] == '?') {
            if (j == n - 1)
              tmp += dp[(i + 1) % 2][0][nexts][0];
            else
              tmp += dp[i % 2][j + 1][nexts][1];
          }

          if (str[i][j] == 'O' || str[i][j] == '?') {
            if (l) {
              if (j == n - 1)
                tmp += dp[(i + 1) % 2][0][nexts | (1 << n - 2)][0];
              else
                tmp += dp[i % 2][j + 1][nexts | (1 << n - 2)][0];
            } else {
              if (j == n - 1)
                tmp += dp[(i + 1) % 2][0][nexts][0];
              else
                tmp += dp[i % 2][j + 1][nexts][0];
            }
          }

          if (str[i][j] == 'I' || str[i][j] == '?') {
            if (k & 1) {
              tmp += cnt[i][j];
            } else {
              if (j == n - 1)
                tmp += dp[(i + 1) % 2][0][nexts][0];
              else
                tmp += dp[i % 2][j + 1][nexts][0];
            }
          }

          dp[i % 2][j][k][l] = tmp % MOD;
        }
      }
    }
  }

  cout << dp[0][0][0][0] << endl;

  return 0;
}