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

#include <bits/stdc++.h>
#define XX first
#define YY second
#define pb emplace_back
#define FOR(i, a, b) for (int(i) = (a); i < (b); ++(i))
#define EFOR(i, a, b) for (int(i) = (a); i <= (b); ++(i))
#define rep(X, Y) for (int(X) = 0; (X) < (Y); ++(X))
#define REP rep
#define rrep(X, Y) for (int(X) = (Y)-1; (X) >= 0; --(X))
#define all(X) (X).begin(), (X).end()
#define eb emplace_back

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef ll LL;
typedef pii PII;
typedef pll PLL;
const ll MOD = 1e9 + 7;

#define rall(X) (X).rbegin(), (X).rend()
#define UNIQUE(X) (X).erase(unique(all(X)), (X).end())
#define reps(X, S, Y) for (int(X) = S; (X) < (Y); ++(X))
#define rreps(X, S, Y) for (int(X) = (Y)-1; (X) >= (S); --(X))
template <class T> inline bool MX(T &l, const T &r) {
  return l < r ? l = r, 1 : 0;
}
template <class T> inline bool MN(T &l, const T &r) {
  return l > r ? l = r, 1 : 0;
}

template <ll mod> struct ModInt {
  using M = ModInt;
  ll a;
  M &put(ll v) {
    a = (v < mod) ? v : v - mod;
    return *this;
  }
  ModInt(ll v = 0) { put(v % mod + mod); }
  M operator+(M x) { return M().put(a + x.a); }
  M operator-(M x) { return M().put(a + mod - x.a); }
  M operator*(M x) { return M().put(a * x.a % mod); }
  M operator/(M x) { return x.inv() * a; }
  M &operator+=(M x) { return *this = *this + x; };
  M &operator-=(M x) { return *this = *this - x; };
  M &operator*=(M x) { return *this = *this * x; };
  M &operator/=(M x) { return *this = *this / x; };
  bool operator==(M x) { return a == x.a; }
  M pow(ll m) {
    M x = *this, res = 1;
    while (m) {
      if (m & 1)
        res *= x;
      x *= x;
      m >>= 1;
    }
    return res;
  }
  M inv() { return pow(mod - 2); }
};
using mint = ModInt<998244353>;

int H;
int W;
int hlim;
int wlim;
int rowb[14];
int colb[14];
int field[14][14];
mint fact[100];
mint tmp[14][14][2];
vector<vector<mint>> dp;
vector<vector<mint>> WB;
vector<vector<mint>> BW;

mint Comb(int n, int k) {
  assert(0 <= k && k <= n);
  return fact[n] / fact[k] / fact[n - k];
}

// Zeta Transform g(T)=\\sum_{S \\subset T}f(S)
template <class T, class F> inline void FZT(vector<T> &f, F add) {
  int n = __lg(f.size());
  int lim = 1 << n;
  rep(i, n) {
    rep(j, lim) {
      if (~j >> i & 1)
        f[j | 1 << i] = add(f[j | 1 << i], f[j]);
    }
  }
}
// Modoebius Transform g(T)=\\sum_{S \\subset T}(-1)^{|T\\S|}f(S)
template <class T, class F> inline void FMT(vector<T> &f, F sub) {
  int n = __lg(f.size());
  int lim = 1 << n;
  rep(i, n) {
    rep(j, lim) {
      if (~j >> i & 1)
        f[j | 1 << i] = sub(f[j | 1 << i], f[j]);
    }
  }
}
// O(nlog^2n) f*g(S)=\\sum_{U∪V=S, U∩V=\\emptyset } f(U)*g(V)
template <class T, class F>
inline vector<vector<T>> RankedFZT(vector<T> &f, F add) {
  int n = __lg(f.size());
  int lim = 1 << n;
  vector<vector<T>> ret(n + 1, vector<T>(f.size()));
  rep(i, lim) ret[__builtin_popcount(i)][i] = f[i];
  rep(i, n + 1) FZT(ret[i], add);
  return ret;
}
template <class T, class F, class G>
inline vector<T> ExactConv(vector<T> &f, vector<T> &g, F add, G sub) {
  int n = __lg(f.size());
  int lim = 1 << n;
  auto rf = RankedFZT(f, add);
  auto rg = RankedFZT(g, add);
  vector<vector<T>> c(n + 1, vector<T>(f.size()));
  rep(k, n + 1) {
    rep(j, k + 1) rep(st, lim) { c[k][st] += rf[j][st] * rg[k - j][st]; }
    FZT(c[k], sub);
  }
  vector<T> ret(lim);
  rep(i, lim) ret[i] = c[__builtin_popcount(i)][i];
  return ret;
}

signed main() {
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(0);

  fact[0] = 1;
  reps(i, 1, 100) { fact[i] = fact[i - 1] * i; }

  cin >> H >> W;
  hlim = 1 << H;
  wlim = 1 << W;
  rep(i, H) {
    rep(j, W) {
      char c;
      cin >> c;
      if (c == '#')
        field[i][j] = 1;
      else if (c == '.')
        field[i][j] = 0;
      else
        assert(0);
    }
  }
  rep(i, H) { rrep(j, W) rowb[i] = (rowb[i] << 1) | field[i][j]; }
  rep(j, W) { rrep(i, H) colb[j] = (colb[j] << 1) | field[i][j]; }

  tmp[0][0][0] = 1;
  tmp[0][0][1] = 1;
  rep(i, H + 1) {
    rep(j, W + 1) {
      reps(k, 1, H + 1) {
        if (i + k > H)
          break;
        tmp[i + k][j][1] += tmp[i][j][0] * Comb(i + k, k);
      }
      reps(k, 1, W + 1) {
        if (j + k > W)
          break;
        tmp[i][j + k][0] += tmp[i][j][1] * Comb(j + k, k);
      }
    }
  }
  dp.resize(hlim, vector<mint>(wlim));
  rep(i, H + 1) {
    rep(j, W + 1) { dp[i][j] = tmp[i][j][0] + tmp[i][j][1]; }
  }
  dp[0][0] = 1;

  vector<vector<mint>> conv(H + 1, vector<mint>(W + 1));
  rep(s, H + 1) {
    rep(t, W + 1) {
      rep(a, s + 1) {
        rep(b, t + 1) {
          conv[s][t] += Comb(s, a) * Comb(t, b) * dp[a][b] * dp[s - a][t - b];
        }
      }
    }
  }

  mint ans = 0;
  rep(hst, hlim) {
    rep(wst, wlim) {
      bool ng = 0;
      int hexc = ~hst & (hlim - 1);
      int wexc = ~wst & (wlim - 1);
      rep(j, W) {
        if (wst >> j & 1)
          continue;
        if ((colb[j] & hexc) == hexc)
          ng = 1;
        if ((~colb[j] & hexc) == hexc)
          ng = 1;
      }
      rep(i, H) {
        if (hst >> i & 1)
          continue;
        if ((rowb[i] & wexc) == wexc)
          ng = 1;
        if ((~rowb[i] & wexc) == wexc)
          ng = 1;
      }
      int hcnt = __builtin_popcount(hst);
      int wcnt = __builtin_popcount(wst);
      if (hcnt == H && wcnt == W)
        ans += dp[H][W];
      else if (!ng)
        ans += conv[hcnt][wcnt];
    }
  }
  cout << ans.a << endl;
}


Error: TLE

Fixed submission:

#include <bits/stdc++.h>
#define XX first
#define YY second
#define pb emplace_back
#define FOR(i, a, b) for (int(i) = (a); i < (b); ++(i))
#define EFOR(i, a, b) for (int(i) = (a); i <= (b); ++(i))
#define rep(X, Y) for (int(X) = 0; (X) < (Y); ++(X))
#define REP rep
#define rrep(X, Y) for (int(X) = (Y)-1; (X) >= 0; --(X))
#define all(X) (X).begin(), (X).end()
#define eb emplace_back

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef ll LL;
typedef pii PII;
typedef pll PLL;
const ll MOD = 1e9 + 7;

#define rall(X) (X).rbegin(), (X).rend()
#define UNIQUE(X) (X).erase(unique(all(X)), (X).end())
#define reps(X, S, Y) for (int(X) = S; (X) < (Y); ++(X))
#define rreps(X, S, Y) for (int(X) = (Y)-1; (X) >= (S); --(X))
template <class T> inline bool MX(T &l, const T &r) {
  return l < r ? l = r, 1 : 0;
}
template <class T> inline bool MN(T &l, const T &r) {
  return l > r ? l = r, 1 : 0;
}

template <ll mod> struct ModInt {
  using M = ModInt;
  ll a;
  M &put(ll v) {
    a = (v < mod) ? v : v - mod;
    return *this;
  }
  ModInt(ll v = 0) { put(v % mod + mod); }
  M operator+(M x) { return M().put(a + x.a); }
  M operator-(M x) { return M().put(a + mod - x.a); }
  M operator*(M x) { return M().put(a * x.a % mod); }
  M operator/(M x) { return x.inv() * a; }
  M &operator+=(M x) { return *this = *this + x; };
  M &operator-=(M x) { return *this = *this - x; };
  M &operator*=(M x) { return *this = *this * x; };
  M &operator/=(M x) { return *this = *this / x; };
  bool operator==(M x) { return a == x.a; }
  M pow(ll m) {
    M x = *this, res = 1;
    while (m) {
      if (m & 1)
        res *= x;
      x *= x;
      m >>= 1;
    }
    return res;
  }
  M inv() { return pow(mod - 2); }
};
using mint = ModInt<998244353>;

int H;
int W;
int hlim;
int wlim;
int rowb[14];
int colb[14];
int field[14][14];
mint fact[100];
mint tmp[14][14][2];
vector<vector<mint>> dp;
vector<vector<mint>> WB;
vector<vector<mint>> BW;

mint Comb(int n, int k) {
  assert(0 <= k && k <= n);
  return fact[n] / fact[k] / fact[n - k];
}

// Zeta Transform g(T)=\\sum_{S \\subset T}f(S)
template <class T, class F> inline void FZT(vector<T> &f, F add) {
  int n = __lg(f.size());
  int lim = 1 << n;
  rep(i, n) {
    rep(j, lim) {
      if (~j >> i & 1)
        f[j | 1 << i] = add(f[j | 1 << i], f[j]);
    }
  }
}
// Modoebius Transform g(T)=\\sum_{S \\subset T}(-1)^{|T\\S|}f(S)
template <class T, class F> inline void FMT(vector<T> &f, F sub) {
  int n = __lg(f.size());
  int lim = 1 << n;
  rep(i, n) {
    rep(j, lim) {
      if (~j >> i & 1)
        f[j | 1 << i] = sub(f[j | 1 << i], f[j]);
    }
  }
}
// O(nlog^2n) f*g(S)=\\sum_{U∪V=S, U∩V=\\emptyset } f(U)*g(V)
template <class T, class F>
inline vector<vector<T>> RankedFZT(vector<T> &f, F add) {
  int n = __lg(f.size());
  int lim = 1 << n;
  vector<vector<T>> ret(n + 1, vector<T>(f.size()));
  rep(i, lim) ret[__builtin_popcount(i)][i] = f[i];
  rep(i, n + 1) FZT(ret[i], add);
  return ret;
}
template <class T, class F, class G>
inline vector<T> ExactConv(vector<T> &f, vector<T> &g, F add, G sub) {
  int n = __lg(f.size());
  int lim = 1 << n;
  auto rf = RankedFZT(f, add);
  auto rg = RankedFZT(g, add);
  vector<vector<T>> c(n + 1, vector<T>(f.size()));
  rep(k, n + 1) {
    rep(j, k + 1) rep(st, lim) { c[k][st] += rf[j][st] * rg[k - j][st]; }
    FZT(c[k], sub);
  }
  vector<T> ret(lim);
  rep(i, lim) ret[i] = c[__builtin_popcount(i)][i];
  return ret;
}

signed main() {
  ios_base::sync_with_stdio(false);
  cout << fixed << setprecision(0);

  fact[0] = 1;
  reps(i, 1, 100) { fact[i] = fact[i - 1] * i; }

  cin >> H >> W;
  hlim = 1 << H;
  wlim = 1 << W;
  rep(i, H) {
    rep(j, W) {
      char c;
      cin >> c;
      if (c == '#')
        field[i][j] = 1;
      else if (c == '.')
        field[i][j] = 0;
      else
        assert(0);
    }
  }
  rep(i, H) { rrep(j, W) rowb[i] = (rowb[i] << 1) | field[i][j]; }
  rep(j, W) { rrep(i, H) colb[j] = (colb[j] << 1) | field[i][j]; }

  tmp[0][0][0] = 1;
  tmp[0][0][1] = 1;
  rep(i, H + 1) {
    rep(j, W + 1) {
      reps(k, 1, H + 1) {
        if (i + k > H)
          break;
        tmp[i + k][j][1] += tmp[i][j][0] * Comb(i + k, k);
      }
      reps(k, 1, W + 1) {
        if (j + k > W)
          break;
        tmp[i][j + k][0] += tmp[i][j][1] * Comb(j + k, k);
      }
    }
  }
  dp.resize(hlim, vector<mint>(wlim));
  rep(i, H + 1) {
    rep(j, W + 1) { dp[i][j] = tmp[i][j][0] + tmp[i][j][1]; }
  }
  dp[0][0] = 1;

  vector<mint> f(hlim * wlim);
  rep(hst, hlim) {
    rep(wst, wlim) {
      int hcnt = __builtin_popcount(hst);
      int wcnt = __builtin_popcount(wst);
      f[(hst << W) | wst] = dp[hcnt][wcnt];
    }
  }
  auto conv = ExactConv(
      f, f, [](mint a, mint b) { return a + b; },
      [](mint a, mint b) { return a - b; });
  // rep(hst, hlim) {
  //   rep(wst, wlim) {
  //     cout << "c[" << hst << ", " << wst << "]: " << conv[(hst << W) |
  //     wst].a; cout << endl;
  //   }
  // }

  mint ans = 0;
  rep(hst, hlim) {
    rep(wst, wlim) {
      bool ng = 0;
      int hexc = ~hst & (hlim - 1);
      int wexc = ~wst & (wlim - 1);
      rep(j, W) {
        if (wst >> j & 1)
          continue;
        if ((colb[j] & hexc) == hexc)
          ng = 1;
        if ((~colb[j] & hexc) == hexc)
          ng = 1;
      }
      rep(i, H) {
        if (hst >> i & 1)
          continue;
        if ((rowb[i] & wexc) == wexc)
          ng = 1;
        if ((~rowb[i] & wexc) == wexc)
          ng = 1;
      }
      if (hst == hlim - 1 && wst == wlim - 1)
        ans += dp[H][W];
      else if (!ng)
        ans += conv[(hst << W) | wst];
    }
  }
  cout << ans.a << endl;
}