Problem p03562 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <set>

#define fo(i, a, b) for (int i = a; i <= b; i++)
#define fd(i, a, b) for (int i = a; i >= b; i--)

using namespace std;

typedef long long LL;
typedef double db;

const int L = 8005;
const int N = 8005;
const int mo = 998244353;

bitset<L> a[N], Lim;
int n;
int key[N];
LL mi[L];

void getbit(bitset<L> &a) {
  char s[L];
  scanf("%s", s + 1);
  int len = strlen(s + 1);
  fo(i, 0, len - 1) a[i] = s[len - i] - '0';
}

bitset<L> trs(bitset<L> a, bitset<L> b) {
  int wa, wb;
  fd(i, 4000, 0) if (a[i]) {
    wa = i;
    break;
  }
  fd(i, 4000, 0) if (b[i]) {
    wb = i;
    break;
  }
  if (wa < wb)
    swap(a, b), swap(wa, wb);
  while (wb > -1) {
    a = a ^ (b << (wa - wb));
    bool fd = 0;
    fd(i, wa, 0) if (a[i]) {
      wa = i;
      fd = 1;
      break;
    }
    if (!fd)
      wa = -1;
    if (wa < wb)
      swap(a, b), swap(wa, wb);
  }
  return a;
}

int main() {
  mi[0] = 1;
  fo(i, 1, 4000) mi[i] = mi[i - 1] * 2 % mo;
  scanf("%d", &n);
  getbit(Lim);
  fo(i, 1, n) getbit(a[i]);
  int n_ = 0;
  fo(i, 1, n) {
    fo(j, 1, i - 1) if (a[i][key[j]]) a[i] = a[i] ^ a[j];
    int w = -1;
    fd(x, 4000, 0) if (a[i][x]) {
      w = x;
      break;
    }
    key[i] = w;
    if (w != -1) {
      key[++n_] = w;
      a[n_] = a[i];
    }
  }
  n = n_;
  int pre = 0;
  for (bool pd = 1; pd;) {
    int pn = n;
    pd = 0;
    int w = (pre == 0) ? n : pre;
    fo(i, 1, w) fo(j, pre + 1, pn) if (i != j) {
      bitset<L> now = trs(a[i], a[j]);
      fo(p, 1, n) if (now[key[p]]) now = now ^ a[p];
      if (now.count() > 0) {
        a[++n] = now;
        key[n] = 0;
        fd(x, 4000, 0) if (now[x]) {
          key[n] = x;
          break;
        }
      }
    }
    pre = pn;
  }
  int keyw = 1;
  fo(i, 2, n) if (key[i] < key[keyw]) keyw = i;
  int w = 0;
  fd(i, 4000, 0) if (Lim[i]) {
    w = i;
    break;
  }
  LL ans = 0;
  fd(i, w, key[keyw]) if (Lim[i]) ans = (ans + mi[i - key[keyw]]) % mo;
  bitset<L> now;
  fo(i, 0, 4000) now = 0;
  fd(i, w, key[keyw]) if (Lim[i] != now[i]) now =
      now ^ (a[keyw] << (i - key[keyw]));
  int prefer = 1;
  fd(i, key[keyw], 0) if (Lim[i] != now[i]) {
    if (now[i] > Lim[i])
      prefer = 0;
    break;
  }
  ans = (ans + prefer) % mo;
  printf("%lld\n", ans);
  return 0;
}

Fixed submission:
#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <set>

#define fo(i, a, b) for (int i = a; i <= b; i++)
#define fd(i, a, b) for (int i = a; i >= b; i--)

using namespace std;

typedef long long LL;
typedef double db;

const int L = 8005;
const int N = 8005;
const int mo = 998244353;

bitset<L> a[N], Lim;
int n;
int key[N];
LL mi[L];

void getbit(bitset<L> &a) {
  char s[L];
  scanf("%s", s + 1);
  int len = strlen(s + 1);
  fo(i, 0, len - 1) a[i] = s[len - i] - '0';
}

bitset<L> trs(bitset<L> a, bitset<L> b) {
  int wa, wb;
  fd(i, 4000, 0) if (a[i]) {
    wa = i;
    break;
  }
  fd(i, 4000, 0) if (b[i]) {
    wb = i;
    break;
  }
  if (wa < wb)
    swap(a, b), swap(wa, wb);
  while (wb > -1) {
    a = a ^ (b << (wa - wb));
    bool fd = 0;
    fd(i, wa, 0) if (a[i]) {
      wa = i;
      fd = 1;
      break;
    }
    if (!fd)
      wa = -1;
    if (wa < wb)
      swap(a, b), swap(wa, wb);
  }
  return a;
}

int main() {
  mi[0] = 1;
  fo(i, 1, 4000) mi[i] = mi[i - 1] * 2 % mo;
  scanf("%d", &n);
  getbit(Lim);
  fo(i, 1, n) getbit(a[i]);
  int n_ = 0;
  fo(i, 1, n) {
    fo(j, 1, i - 1) if (a[i][key[j]]) a[i] = a[i] ^ a[j];
    if (a[i].count() == 0)
      continue;
    int w = -1;
    fd(x, 4000, 0) if (a[i][x]) {
      w = x;
      break;
    }
    key[i] = w;
    if (w != -1) {
      key[++n_] = w;
      a[n_] = a[i];
    }
  }
  n = n_;
  int pre = 0;
  for (bool pd = 1; pd;) {
    int pn = n;
    pd = 0;
    int w = (pre == 0) ? n : pre;
    fo(i, 1, w) fo(j, pre + 1, pn) if (i != j) {
      bitset<L> now = trs(a[i], a[j]);
      fo(p, 1, n) if (now[key[p]]) now = now ^ a[p];
      if (now.count() > 0) {
        a[++n] = now;
        key[n] = 0;
        fd(x, 4000, 0) if (now[x]) {
          key[n] = x;
          break;
        }
      }
    }
    pre = pn;
  }
  int keyw = 1;
  fo(i, 2, n) if (key[i] < key[keyw]) keyw = i;
  int w = 0;
  fd(i, 4000, 0) if (Lim[i]) {
    w = i;
    break;
  }
  LL ans = 0;
  fd(i, w, key[keyw]) if (Lim[i]) ans = (ans + mi[i - key[keyw]]) % mo;
  bitset<L> now;
  fo(i, 0, 4000) now = 0;
  fd(i, w, key[keyw]) if (Lim[i] != now[i]) now =
      now ^ (a[keyw] << (i - key[keyw]));
  int prefer = 1;
  fd(i, key[keyw], 0) if (Lim[i] != now[i]) {
    if (now[i] > Lim[i])
      prefer = 0;
    break;
  }
  ans = (ans + prefer) % mo;
  printf("%lld\n", ans);
  return 0;
}