Problem p03595 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>

#define INF 1000000010
#define INFLL ((1LL << 62) - 5)
#define FO(i, a, b) for (int(i) = (a); (i) < (b); ++(i))
#define OF(i, a, b) for (int(i) = (a)-1; (i) >= (b); --(i))
#define SZ(v) int(v.size())

using namespace std;
// PAIRS:
#define mp make_pair
#define fi first
#define se second
#define pb push_back
typedef pair<int, int> pii;
typedef long long ll;

/*~~~~TEMPLATE END~~~~*/

// DEBUGS:
// #define DEBUG

#ifdef DEBUG
#define dprintf printf
#else
#define dprintf(...)
#endif

const long long MOD = 998244353;
const ll MAX_N = 100005;

ll inv[MAX_N * 4 + 5];
ll fact[MAX_N * 4 + 5];
ll invfact[MAX_N * 4 + 5];

ll minv(ll c) {
  ll ret = 1;
  ll cP = c;
  FO(i, 0, 31) {
    if ((MOD - 2) & (1 << i)) {
      ret = (ret * cP) % MOD;
    }
    cP = (cP * cP) % MOD;
  }
  return ret;
}

void precomp() {
  FO(i, 1, 400010) { inv[i] = minv(i); }
  fact[0] = 1;
  FO(i, 1, 400010) fact[i] = (fact[i - 1] * i) % MOD;
  invfact[0] = 1;
  FO(i, 1, 400010) invfact[i] = (invfact[i - 1] * inv[i]) % MOD;
}

ll chs(ll a, ll b) {
  return ((fact[a] * invfact[b]) % MOD * invfact[a - b]) % MOD;
}

struct solver {
  int N, M;
  vector<int> vAm;
  vector<int> lV;
  vector<int> rV;
  solver(int __N, int _M, vector<int> &_vAm, vector<int> &_lV,
         vector<int> &_rV) {
    N = __N;
    M = _M;
    vAm = _vAm;
    lV = _lV;
    rV = _rV;
  }
  ll solve() {
    // rAm contains right side vals, hori must occur.
    vector<ll> rAm;
    ll wAm = 0;
    for (int i : rV)
      wAm += i;
    ll hAm = 0;
    OF(i, M, 0) {
      if (wAm == 0) {
        if (hAm > 0)
          rAm.pb(0);
        else
          rAm.pb(1);
      } else {
        rAm.pb(chs(wAm + hAm - 1, wAm - 1));
      }
      hAm += vAm[i];
    }
    reverse(rAm.begin(), rAm.end());
    FO(i, 0, M) dprintf("%lld ", rAm[i]);
    dprintf("\n");
    // lAm contains left side vals, hori need not occur.
    vector<ll> lAm;
    wAm = 0;
    for (int i : lV)
      wAm += i;
    hAm = 0;
    FO(i, 0, M) {
      if (wAm == 0) {
        if (hAm > 0)
          lAm.pb(0);
        else
          lAm.pb(1);
      } else {
        lAm.pb(chs(wAm + hAm - 1, wAm - 1));
      }
      hAm += vAm[i];
    }
    FO(i, 0, M) dprintf("%lld ", lAm[i]);
    dprintf("\n");
    FO(i, 0, M)
    if (!vAm[i])
      lAm[i] = 0;
    FO(i, 0, M) {
      if (i)
        lAm[i] += lAm[i - 1];
      if (vAm[i] == 2)
        lAm[i] *= 2;
      lAm[i] %= MOD;
    }
    ll ans = 0;
    FO(i, 0, M) {
      if (vAm[i]) {
        ans += (lAm[i] * rAm[i]) % MOD;
        ans %= MOD;
      }
    }
    return ans;
  }
};

int N, M;
vector<int> a, b, c, d;

int main() {
  precomp();
  scanf("%d %d", &N, &M);
  FO(i, 0, N) {
    char t;
    scanf(" %c", &t);
    t = t - '0';
    a.pb(t);
  }
  FO(i, 0, N) {
    char t;
    scanf(" %c", &t);
    t = t - '0';
    b.pb(t);
  }
  FO(i, 0, M) {
    char t;
    scanf(" %c", &t);
    t = t - '0';
    c.pb(t);
  }
  FO(i, 0, M) {
    char t;
    scanf(" %c", &t);
    t = t - '0';
    d.pb(t);
  }
  int s = 0;
  FO(i, 0, N) s += a[i] + b[i];
  FO(i, 0, M) s += c[i] + b[i];
  if (!s) {
    printf("1\n");
    return 0;
  }
  ll ans = 0;
  FO(i, 0, 2) {
    vector<int> t;
    FO(i, 0, M) { t.pb(c[i] + d[i]); }
    solver s(N, M, t, a, b);
    ans += s.solve();
    dprintf("ans: %lld\n", ans);

    swap(N, M);
    swap(a, c);
    swap(b, d);
  }
  printf("%lld\n", ans % MOD);
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>

#define INF 1000000010
#define INFLL ((1LL << 62) - 5)
#define FO(i, a, b) for (int(i) = (a); (i) < (b); ++(i))
#define OF(i, a, b) for (int(i) = (a)-1; (i) >= (b); --(i))
#define SZ(v) int(v.size())

using namespace std;
// PAIRS:
#define mp make_pair
#define fi first
#define se second
#define pb push_back
typedef pair<int, int> pii;
typedef long long ll;

/*~~~~TEMPLATE END~~~~*/

// DEBUGS:
// #define DEBUG

#ifdef DEBUG
#define dprintf printf
#else
#define dprintf(...)
#endif

const long long MOD = 998244353;
const ll MAX_N = 100005;

ll inv[MAX_N * 4 + 5];
ll fact[MAX_N * 4 + 5];
ll invfact[MAX_N * 4 + 5];

ll minv(ll c) {
  ll ret = 1;
  ll cP = c;
  FO(i, 0, 31) {
    if ((MOD - 2) & (1 << i)) {
      ret = (ret * cP) % MOD;
    }
    cP = (cP * cP) % MOD;
  }
  return ret;
}

void precomp() {
  FO(i, 1, 400010) { inv[i] = minv(i); }
  fact[0] = 1;
  FO(i, 1, 400010) fact[i] = (fact[i - 1] * i) % MOD;
  invfact[0] = 1;
  FO(i, 1, 400010) invfact[i] = (invfact[i - 1] * inv[i]) % MOD;
}

ll chs(ll a, ll b) {
  return ((fact[a] * invfact[b]) % MOD * invfact[a - b]) % MOD;
}

struct solver {
  int N, M;
  vector<int> vAm;
  vector<int> lV;
  vector<int> rV;
  solver(int __N, int _M, vector<int> &_vAm, vector<int> &_lV,
         vector<int> &_rV) {
    N = __N;
    M = _M;
    vAm = _vAm;
    lV = _lV;
    rV = _rV;
  }
  ll solve() {
    // rAm contains right side vals, hori must occur.
    vector<ll> rAm;
    ll wAm = 0;
    for (int i : rV)
      wAm += i;
    ll hAm = 0;
    OF(i, M, 0) {
      if (wAm == 0) {
        if (hAm > 0)
          rAm.pb(0);
        else
          rAm.pb(1);
      } else {
        rAm.pb(chs(wAm + hAm - 1, wAm - 1));
      }
      hAm += vAm[i];
    }
    reverse(rAm.begin(), rAm.end());
    FO(i, 0, M) dprintf("%lld ", rAm[i]);
    dprintf("\n");
    // lAm contains left side vals, hori need not occur.
    vector<ll> lAm;
    wAm = 0;
    for (int i : lV)
      wAm += i;
    hAm = 0;
    FO(i, 0, M) {
      if (wAm == 0) {
        if (hAm > 0)
          lAm.pb(0);
        else
          lAm.pb(1);
      } else {
        lAm.pb(chs(wAm + hAm - 1, wAm - 1));
      }
      hAm += vAm[i];
    }
    FO(i, 0, M) dprintf("%lld ", lAm[i]);
    dprintf("\n");
    FO(i, 0, M)
    if (!vAm[i])
      lAm[i] = 0;
    FO(i, 0, M) {
      if (i)
        lAm[i] += lAm[i - 1];
      if (vAm[i] == 2)
        lAm[i] *= 2;
      lAm[i] %= MOD;
    }
    ll ans = 0;
    FO(i, 0, M) {
      if (vAm[i]) {
        ans += (lAm[i] * rAm[i]) % MOD;
        ans %= MOD;
      }
    }
    return ans;
  }
};

int N, M;
vector<int> a, b, c, d;

int main() {
  precomp();
  scanf("%d %d", &N, &M);
  FO(i, 0, N) {
    char t;
    scanf(" %c", &t);
    t = t - '0';
    a.pb(t);
  }
  FO(i, 0, N) {
    char t;
    scanf(" %c", &t);
    t = t - '0';
    b.pb(t);
  }
  FO(i, 0, M) {
    char t;
    scanf(" %c", &t);
    t = t - '0';
    c.pb(t);
  }
  FO(i, 0, M) {
    char t;
    scanf(" %c", &t);
    t = t - '0';
    d.pb(t);
  }
  int s = 0;
  FO(i, 0, N) s += a[i] + b[i];
  FO(i, 0, M) s += c[i] + d[i];
  if (!s) {
    printf("1\n");
    return 0;
  }
  ll ans = 0;
  FO(i, 0, 2) {
    vector<int> t;
    FO(i, 0, M) { t.pb(c[i] + d[i]); }
    solver s(N, M, t, a, b);
    ans += s.solve();
    dprintf("ans: %lld\n", ans);

    swap(N, M);
    swap(a, c);
    swap(b, d);
  }
  printf("%lld\n", ans % MOD);
  return 0;
}