Problem p02653 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>

using namespace std;

int sz[2], N, s00p[5009][2], dp[2][5009][2][2], s[5009][5009][2][2];
const int mod = 1e9 + 7;

int add(int x, int y) {
  int ans = x + y;
  if (ans >= mod)
    ans -= mod;
  return ans;
}
int subtract(int x, int y) {
  if (x >= y)
    return x - y;
  return x - y + mod;
}
int mul(int x, int y) { return 1LL * x * y % mod; }
void adto(int &x, int y) {
  x += y;
  if (x >= mod)
    x -= mod;
}

int power(int a, int b) {
  int p = 1;
  for (int i = 0; (1 << i) <= b; i++) {
    if (b & (1 << i))
      p = mul(p, a);
    a = mul(a, a);
  }
  return p;
}

int fac[2000009], inv[2000009];
void Prec(int lim) {
  fac[0] = inv[0] = 1;
  for (int i = 1; i <= lim; i++)
    fac[i] = mul(fac[i - 1], i);
  inv[lim] = power(fac[lim], mod - 2);
  for (int i = lim - 1; i >= 0; i--)
    inv[i] = mul(inv[i + 1], i + 1);
}
int comb(int N, int K) {
  if (K > N || N < 0 || K < 0)
    return 0;
  int ans = mul(fac[N], inv[N - K]);
  ans = mul(ans, inv[K]);
  return ans;
}

void addDiag(int i, int j, int k, int p, int l, int r, int val) {
  r = min(r, N - i);
  if (l < 1)
    l = 1;
  if (l > r)
    return;
  // if (i == j && p == 1 && k == 0)
  //   printf ("%d+, %d+, %d, %d    +%d on [%d, %d]\\n", i, j, k, p, val, l, r);
  adto(s[i + l][j + l][k][p], val);
  s[i + r + 1][j + r + 1][k][p] = subtract(s[i + r + 1][j + r + 1][k][p], val);
}

void add00p(int i, int l, int r, int p, int val) {
  r = min(r, N - i);
  if (l > r)
    return;
  adto(s00p[i + l][p], val);
  s00p[i + r + 1][p] = subtract(s00p[i + r + 1][p], val);
}

int bruteDp[20][20][2][2];
void brute(int dp[20][20][2][2]) {
  for (int i = 1; i <= N; i++) {
    adto(dp[i][i * (i >= sz[0])][0][(i * (i >= sz[0])) >= sz[1]], 1);
    adto(dp[i][i][1][i >= sz[1]], 1);
    for (int j = 0; j <= i; j++)
      for (int k = 0; k < 2; k++)
        for (int p = 0; p < 2; p++)
          if (dp[i][j][k][p])
            for (int j2 = 1; i + j2 <= N; j2++) {
              int newJ = j + j2;
              if (k == 1 && j2 < sz[0])
                newJ = 0;
              adto(dp[i + j2][newJ][k ^ 1][p | (newJ >= sz[1])],
                   dp[i][j][k][p]);
            }
  }
}

int main() {
  // freopen ("input", "r", stdin);
  // freopen ("output", "w", stdout);

  scanf("%d %d %d", &N, &sz[0], &sz[1]);
  if (sz[0] > sz[1])
    swap(sz[0], sz[1]);
  // if (N < 15)
  //   brute (bruteDp);
  for (int i = 1; i <= N; i++) {
    memset(dp[i & 1], 0, sizeof(dp[i & 1]));
    adto(dp[i & 1][i * (i >= sz[0])][0][(i * (i >= sz[0])) >= sz[1]], 1);
    adto(dp[i & 1][i][1][i >= sz[1]], 1);
    for (int p = 0; p < 2; p++)
      adto(s00p[i][p], s00p[i - 1][p]), adto(dp[i & 1][0][0][p], s00p[i][p]);
    for (int j = 0; j <= i; j++)
      for (int k = 0; k < 2; k++)
        for (int p = 0; p < 2; p++) {
          if (i > 0 && j > 0)
            adto(s[i][j][k][p], s[i - 1][j - 1][k][p]);
          adto(dp[i & 1][j][k][p], s[i][j][k][p]);
          // if (dp[i][j][k][p] != bruteDp[i][j][k][p])
          //   printf ("wa (%d, %d, %d, %d) -> %d instead of %d\\n", i, j, k, p,
          //   dp[i][j][k][p], bruteDp[i][j][k][p]);
          if (dp[i & 1][j][k][p]) {
            // if (i == 2 && j == 2 && k == 1)
            //   k = 1;
            int curr = dp[i & 1][j][k][p];
            if (k == 1) {
              add00p(i, 1, sz[0] - 1, p, curr);
              addDiag(i, j, 0, p, sz[0], sz[1] - j - 1, curr);
              addDiag(i, j, 0, 1, max(sz[1] - j, sz[0]), N - i, curr);
            } else {
              addDiag(i, j, 1, p, 1, sz[1] - j - 1, curr);
              addDiag(i, j, 1, 1, sz[1] - j, N - i, curr);
            }
            /*                    for (int j2=1; i + j2 <= N; j2++)
                                {
                                    int newJ = j + j2;
                                    if (k == 1 && j2 < sz[0])
                                        newJ = 0;
                                    adto (dp[i + j2][newJ][k ^ 1][p | (newJ >=
               sz[1])], dp[i][j][k][p]);
                                }*/
          }
        }
  }
  int ans = 0;
  for (int j = 0; j <= N; j++)
    for (int k = 0; k < 2; k++)
      adto(ans, dp[N & 1][j][k][1]);
  printf("%d\\n", ans);
  return 0;
}


Error: -11

Fixed submission:

#include <bits/stdc++.h>

using namespace std;

int sz[2], N, s00p[5009][2], dp[2][5009][2][2], s[5009][5009][2][2];
const int mod = 1e9 + 7;

int add(int x, int y) {
  int ans = x + y;
  if (ans >= mod)
    ans -= mod;
  return ans;
}
int subtract(int x, int y) {
  if (x >= y)
    return x - y;
  return x - y + mod;
}
int mul(int x, int y) { return 1LL * x * y % mod; }
void adto(int &x, int y) {
  x += y;
  if (x >= mod)
    x -= mod;
}

int power(int a, int b) {
  int p = 1;
  for (int i = 0; (1 << i) <= b; i++) {
    if (b & (1 << i))
      p = mul(p, a);
    a = mul(a, a);
  }
  return p;
}

int fac[2000009], inv[2000009];
void Prec(int lim) {
  fac[0] = inv[0] = 1;
  for (int i = 1; i <= lim; i++)
    fac[i] = mul(fac[i - 1], i);
  inv[lim] = power(fac[lim], mod - 2);
  for (int i = lim - 1; i >= 0; i--)
    inv[i] = mul(inv[i + 1], i + 1);
}
int comb(int N, int K) {
  if (K > N || N < 0 || K < 0)
    return 0;
  int ans = mul(fac[N], inv[N - K]);
  ans = mul(ans, inv[K]);
  return ans;
}

void addDiag(int i, int j, int k, int p, int l, int r, int val) {
  if (l < 1)
    l = 1;
  if (l > r)
    return;
  // if (i == j && p == 1 && k == 0)
  //   printf ("%d+, %d+, %d, %d    +%d on [%d, %d]\\n", i, j, k, p, val, l, r);
  adto(s[i + l][j + l][k][p], val);
  s[i + r + 1][j + r + 1][k][p] = subtract(s[i + r + 1][j + r + 1][k][p], val);
}

void add00p(int i, int l, int r, int p, int val) {
  if (l > r)
    return;
  adto(s00p[i + l][p], val);
  s00p[i + r + 1][p] = subtract(s00p[i + r + 1][p], val);
}

int bruteDp[20][20][2][2];
void brute(int dp[20][20][2][2]) {
  for (int i = 1; i <= N; i++) {
    adto(dp[i][i * (i >= sz[0])][0][(i * (i >= sz[0])) >= sz[1]], 1);
    adto(dp[i][i][1][i >= sz[1]], 1);
    for (int j = 0; j <= i; j++)
      for (int k = 0; k < 2; k++)
        for (int p = 0; p < 2; p++)
          if (dp[i][j][k][p])
            for (int j2 = 1; i + j2 <= N; j2++) {
              int newJ = j + j2;
              if (k == 1 && j2 < sz[0])
                newJ = 0;
              adto(dp[i + j2][newJ][k ^ 1][p | (newJ >= sz[1])],
                   dp[i][j][k][p]);
            }
  }
}

int main() {
  // freopen ("input", "r", stdin);
  // freopen ("output", "w", stdout);

  scanf("%d %d %d", &N, &sz[0], &sz[1]);
  if (sz[0] > sz[1])
    swap(sz[0], sz[1]);
  // if (N < 15)
  //   brute (bruteDp);
  for (int i = 1; i <= N; i++) {
    memset(dp[i & 1], 0, sizeof(dp[i & 1]));
    adto(dp[i & 1][i * (i >= sz[0])][0][(i * (i >= sz[0])) >= sz[1]], 1);
    adto(dp[i & 1][i][1][i >= sz[1]], 1);
    for (int p = 0; p < 2; p++)
      adto(s00p[i][p], s00p[i - 1][p]), adto(dp[i & 1][0][0][p], s00p[i][p]);
    for (int j = 0; j <= i; j++)
      for (int k = 0; k < 2; k++)
        for (int p = 0; p < 2; p++) {
          if (i > 0 && j > 0)
            adto(s[i][j][k][p], s[i - 1][j - 1][k][p]);
          adto(dp[i & 1][j][k][p], s[i][j][k][p]);
          // if (dp[i][j][k][p] != bruteDp[i][j][k][p])
          //   printf ("wa (%d, %d, %d, %d) -> %d instead of %d\\n", i, j, k, p,
          //   dp[i][j][k][p], bruteDp[i][j][k][p]);
          if (dp[i & 1][j][k][p]) {
            // if (i == 2 && j == 2 && k == 1)
            //   k = 1;
            int curr = dp[i & 1][j][k][p];
            if (k == 1) {
              add00p(i, 1, sz[0] - 1, p, curr);
              addDiag(i, j, 0, p, sz[0], sz[1] - j - 1, curr);
              addDiag(i, j, 0, 1, max(sz[1] - j, sz[0]), N - i, curr);
            } else {
              addDiag(i, j, 1, p, 1, sz[1] - j - 1, curr);
              addDiag(i, j, 1, 1, sz[1] - j, N - i, curr);
            }
            /*                    for (int j2=1; i + j2 <= N; j2++)
                                {
                                    int newJ = j + j2;
                                    if (k == 1 && j2 < sz[0])
                                        newJ = 0;
                                    adto (dp[i + j2][newJ][k ^ 1][p | (newJ >=
               sz[1])], dp[i][j][k][p]);
                                }*/
          }
        }
  }
  int ans = 0;
  for (int j = 0; j <= N; j++)
    for (int k = 0; k < 2; k++)
      adto(ans, dp[N & 1][j][k][1]);
  printf("%d\\n", ans);
  return 0;
}