Problem p02800 (C++) — buggy submission, verdict: Time Limit Exceeded

/* cerberus97 - Hanit Banga */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>

using namespace std;

#define pb push_back
#define fast_cin()                                                             \\
  ios_base::sync_with_stdio(false);                                            \\
  cin.tie(NULL)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 10, S = (1 << N) + 10, mod = 998244353;

inline void add(int &a, int b) {
  a += b;
  if (a >= mod)
    a -= mod;
}

inline int mul(ll a, int b) { return (a * b) % mod; }

string a[N];
int h, w, cnt[S], p2[N];
int dp[S][S][2][2];
bool seen[S][S][2][2], dp2[S][S], seen2[S][S];

int main() {
  fast_cin();
  cin >> h >> w;
  for (int i = 0; i < h; ++i) {
    cin >> a[i];
    for (auto &c : a[i]) {
      c = (1 << (c == '#'));
    }
  }
  for (int i = 0; i <= max(h, w); ++i) {
    p2[i] = (1 << i);
  }
  int mrows = (1 << h), mcols = (1 << w);
  for (int mask = 0; mask < max(mrows, mcols); ++mask) {
    cnt[mask] = __builtin_popcount(mask);
  }
  for (int rows = 0; rows < mrows; ++rows) {
    for (int cols = 0; cols < mcols; ++cols) {
      bool &ans = dp2[rows][cols];
      vector<int> cr(h, 0), cc(w, 0);
      for (int i = 0; i < h; ++i) {
        if (!((rows >> i) & 1)) {
          continue;
        }
        for (int j = 0; j < w; ++j) {
          if (!((cols >> j) & 1)) {
            continue;
          }
          cr[i] |= a[i][j];
          cc[j] |= a[i][j];
        }
      }
      ans = true;
      for (int i = 0; i < h; ++i) {
        ans &= !((rows >> i) & 1) or (cr[i] == 3);
      }
      for (int j = 0; j < w; ++j) {
        ans &= !((cols >> j) & 1) or (cc[j] == 3);
      }
    }
  }
  for (int rows = 0; rows < mrows; ++rows) {
    for (int cols = 0; cols < mcols; ++cols) {
      for (int turn = 0; turn < 2; ++turn) {
        for (int must = 0; must < 2; ++must) {
          int &ans = dp[rows][cols][turn][must];
          if (!rows or !cols) {
            ans = (must == 0);
          } else {
            add(ans, dp2[rows][cols]);
            int submask = (turn ? cols : rows);
            while (submask) {
              int nrows = rows - (turn ? 0 : submask);
              int ncols = cols - (turn ? submask : 0);
              add(ans, dp[nrows][ncols][turn ^ 1][1]);
              if (must == 0) {
                add(ans, dp[nrows][ncols][turn ^ 1][1]);
                if (cnt[submask] > 1) {
                  add(ans,
                      mul(p2[cnt[submask]] - 2, dp[nrows][ncols][turn ^ 1][0]));
                }
              }
              submask = (submask - 1) & (turn ? cols : rows);
            }
          }
        }
      }
    }
  }
  int ans = 0;
  for (int mask = 0; mask < (1 << w); ++mask) {
    // add(ans, mul(p2[cnt[mask]], solve((1 << h) - 1, (1 << w) - 1 - mask, 0,
    // 0)));
    add(ans, mul(p2[cnt[mask]], dp[(1 << h) - 1][(1 << w) - 1 - mask][0][0]));
  }
  cout << ans << endl;
}

Error: TLE

Fixed submission:

/* cerberus97 - Hanit Banga */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>

using namespace std;

#define pb push_back
#define fast_cin()                                                             \\
  ios_base::sync_with_stdio(false);                                            \\
  cin.tie(NULL)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

const int N = 10, S = (1 << N) + 10, mod = 998244353;

void add(int &a, int b) {
  a += b;
  if (a >= mod)
    a -= mod;
}

int mul(ll a, ll b) { return (a * b) % mod; }

string a[N];
int h, w, cnt[S], p2[N];
int dp[S][S][2][3];
bool seen[S][S][2][3], dp2[S][S], seen2[S][S];

int solve(int rows, int cols, int turn, int must);
bool is_colorful(int rows, int cols);

int main() {
  fast_cin();
  cin >> h >> w;
  for (int i = 0; i < h; ++i) {
    cin >> a[i];
  }
  for (int i = 0; i <= max(h, w); ++i) {
    p2[i] = (1 << i);
  }
  for (int mask = 0; mask < (1 << max(w, h)); ++mask) {
    cnt[mask] = __builtin_popcount(mask);
  }
  int ans = 0;
  for (int mask = 0; mask < (1 << w); ++mask) {
    // for (int mask = 0; mask <= 0; ++mask) {
    add(ans,
        mul(p2[cnt[mask]], solve((1 << h) - 1, (1 << w) - 1 - mask, 0, 0)));
    // cout << mask << ' ' << mul(p2[cnt[mask]], solve((1 << h) - 1, (1 << w) -
    // 1 - mask, 0, 0)) << endl;
  }
  cout << ans << endl;
}

int solve(int rows, int cols, int turn, int must) {
  if (seen[rows][cols][turn][must]) {
    return dp[rows][cols][turn][must];
  } else {
    seen[rows][cols][turn][must] = true;
    int &ans = dp[rows][cols][turn][must];
    if (!rows or !cols) {
      ans = (must == 0);
    } else {
      add(ans, is_colorful(rows, cols));
      int submask = (turn ? cols : rows);
      while (submask) {
        int nrows = rows - (turn ? 0 : submask);
        int ncols = cols - (turn ? submask : 0);
        if (must == 0) {
          add(ans, mul(p2[cnt[submask]] - 2, solve(nrows, ncols, turn ^ 1, 0)));
        }
        if (must != 1) {
          add(ans, solve(nrows, ncols, turn ^ 1, 1));
        }
        if (must != 2) {
          add(ans, solve(nrows, ncols, turn ^ 1, 2));
        }
        submask = (submask - 1) & (turn ? cols : rows);
      }
    }
    // if (ans) {
    // 	cout << rows << ' ' << cols << ' ' << turn << ' ' << must << ' ' << ans
    // << endl;
    // }
    return ans;
  }
}

bool is_colorful(int rows, int cols) {
  if (seen2[rows][cols]) {
    return dp2[rows][cols];
  } else {
    seen2[rows][cols] = true;
    bool &ans = dp2[rows][cols];
    vector<int> cr(h, 0), cc(w, 0);
    for (int i = 0; i < h; ++i) {
      if (!((rows >> i) & 1)) {
        continue;
      }
      for (int j = 0; j < w; ++j) {
        if (!((cols >> j) & 1)) {
          continue;
        }
        cr[i] |= (1 << (a[i][j] == '#'));
        cc[j] |= (1 << (a[i][j] == '#'));
      }
    }
    ans = true;
    for (int i = 0; i < h; ++i) {
      ans &= !((rows >> i) & 1) or (cr[i] == 3);
    }
    for (int j = 0; j < w; ++j) {
      ans &= !((cols >> j) & 1) or (cc[j] == 3);
    }
    return ans;
  }
}