Problem p03003 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cmath> // 変数名にy1が使えなくなるかも…。
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

typedef __int128_t int128_t;
std::istream &
operator>>(std::istream &input,
           int128_t &value) { // int128_tの入力。入力が64bitに収まる前提。
  long long tmp;
  input >> tmp;
  value = tmp;
  return input;
}
std::ostream &
operator<<(std::ostream &output,
           const int128_t value) { // int128_tの出力。出力が64bitに収まる前提。
  output << (long long)value;
  return output;
}

const int MAX_N = 1010;
const int MOD = 1e9 + 7;
int128_t N, M;
int128_t S[MAX_N], T[MAX_N];

int128_t dp[MAX_N][MAX_N][2][2] = {};

int128_t calc(int n, int m, int f1,
              int f2) { // n,mまで選び終わって一致している。
  if (dp[n][m][f1][f2] != -1) {
    return dp[n][m][f1][f2];
  }

  int128_t ret = 0;
  if (n == 0) {
    if (f1 == 1 && f2 == 0) {
      ret = 1;
    } else {
      ret = 0;
    }
  } else if (m == 0) {
    if (f1 == 0 && f2 == 1) {
      ret = 1;
    } else {
      ret = 0;
    }
  } else if (f1 == 1 && f2 == 1) {
    if (S[n] == T[m]) {
      ret += calc(n - 1, m - 1, 0, 0);
      ret += calc(n - 1, m - 1, 1, 0);
      ret += calc(n - 1, m - 1, 0, 1);
      ret += calc(n - 1, m - 1, 1, 1);
      ret %= MOD;
    } else {
      ret = 0;
    }
  } else if (f1 == 0 && f2 == 0) {
    ret += calc(n - 1, m - 1, 0, 0);
    ret += calc(n - 1, m - 1, 1, 0);
    ret += calc(n - 1, m - 1, 0, 1);
    ret += calc(n - 1, m - 1, 1, 1);
    ret %= MOD;
  } else if (f1 == 1) {
    assert(f2 == 0);
    ret += calc(n, m - 1, f1, 0);
    ret += calc(n, m - 1, f1, 1);
    ret %= MOD;
  } else {
    assert(f2 == 1);
    ret += calc(n - 1, m, 0, f2);
    ret += calc(n - 1, m, 1, f2);
    ret %= MOD;
  }

  dp[n][m][f1][f2] = ret;
  return ret;
}

int main(int argc, char **argv) {
  std::cin >> N >> M;

  for (int i = 1; i <= N; i++) {
    std::cin >> S[i];
  }

  for (int i = 1; i <= M; i++) {
    std::cin >> T[i];
  }

  for (int i = 0; i <= N; i++) {
    for (int j = 0; j <= M; j++) {
      dp[i][j][0][0] = -1;
      dp[i][j][0][1] = -1;
      dp[i][j][1][0] = -1;
      dp[i][j][1][1] = -1;
    }
  }
  dp[0][0][1][1] = 1;
  dp[0][0][0][0] = 0;
  dp[0][0][0][1] = 0;
  dp[0][0][1][0] = 0;

  int128_t ret = 0;
  for (int i = 0; i <= N; i++) {
    for (int j = 0; j <= M; j++) {
      ret = (ret + calc(i, j, 1, 1)) % MOD;
      // std::cout << i << " " << j << " " << ret << std::endl;
    }
  }

  /*
  std::cout << dp[2][2][0][0] << std::endl;
  std::cout << dp[2][2][0][1] << std::endl;
  std::cout << dp[2][2][1][0] << std::endl;
  std::cout << dp[2][2][1][1] << std::endl;
  std::cout << std::endl;
  std::cout << dp[3][3][1][1] << std::endl;
  */

  std::cout << ret << std::endl;

  return 0;
}

Fixed submission:
#include <algorithm>
#include <array>
#include <assert.h>
#include <bitset>
#include <cmath> // 変数名にy1が使えなくなるかも…。
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

typedef __int128_t int128_t;
std::istream &
operator>>(std::istream &input,
           int128_t &value) { // int128_tの入力。入力が64bitに収まる前提。
  long long tmp;
  input >> tmp;
  value = tmp;
  return input;
}
std::ostream &
operator<<(std::ostream &output,
           const int128_t value) { // int128_tの出力。出力が64bitに収まる前提。
  output << (long long)value;
  return output;
}

const int MAX_N = 2010;
const int MOD = 1e9 + 7;
int128_t N, M;
int128_t S[MAX_N], T[MAX_N];

int128_t dp[MAX_N][MAX_N][2][2] = {};

int128_t calc(int n, int m, int f1,
              int f2) { // n,mまで選び終わって一致している。
  if (dp[n][m][f1][f2] != -1) {
    return dp[n][m][f1][f2];
  }

  int128_t ret = 0;
  if (n == 0) {
    if (f1 == 1 && f2 == 0) {
      ret = 1;
    } else {
      ret = 0;
    }
  } else if (m == 0) {
    if (f1 == 0 && f2 == 1) {
      ret = 1;
    } else {
      ret = 0;
    }
  } else if (f1 == 1 && f2 == 1) {
    if (S[n] == T[m]) {
      ret += calc(n - 1, m - 1, 0, 0);
      ret += calc(n - 1, m - 1, 1, 0);
      ret += calc(n - 1, m - 1, 0, 1);
      ret += calc(n - 1, m - 1, 1, 1);
      ret %= MOD;
    } else {
      ret = 0;
    }
  } else if (f1 == 0 && f2 == 0) {
    ret += calc(n - 1, m - 1, 0, 0);
    ret += calc(n - 1, m - 1, 1, 0);
    ret += calc(n - 1, m - 1, 0, 1);
    ret += calc(n - 1, m - 1, 1, 1);
    ret %= MOD;
  } else if (f1 == 1) {
    assert(f2 == 0);
    ret += calc(n, m - 1, f1, 0);
    ret += calc(n, m - 1, f1, 1);
    ret %= MOD;
  } else {
    assert(f2 == 1);
    ret += calc(n - 1, m, 0, f2);
    ret += calc(n - 1, m, 1, f2);
    ret %= MOD;
  }

  dp[n][m][f1][f2] = ret;
  return ret;
}

int main(int argc, char **argv) {
  std::cin >> N >> M;

  for (int i = 1; i <= N; i++) {
    std::cin >> S[i];
  }

  for (int i = 1; i <= M; i++) {
    std::cin >> T[i];
  }

  for (int i = 0; i <= N; i++) {
    for (int j = 0; j <= M; j++) {
      dp[i][j][0][0] = -1;
      dp[i][j][0][1] = -1;
      dp[i][j][1][0] = -1;
      dp[i][j][1][1] = -1;
    }
  }
  dp[0][0][1][1] = 1;
  dp[0][0][0][0] = 0;
  dp[0][0][0][1] = 0;
  dp[0][0][1][0] = 0;

  int128_t ret = 0;
  for (int i = 0; i <= N; i++) {
    for (int j = 0; j <= M; j++) {
      ret = (ret + calc(i, j, 1, 1)) % MOD;
      // std::cout << i << " " << j << " " << ret << std::endl;
    }
  }

  /*
  std::cout << dp[2][2][0][0] << std::endl;
  std::cout << dp[2][2][0][1] << std::endl;
  std::cout << dp[2][2][1][0] << std::endl;
  std::cout << dp[2][2][1][1] << std::endl;
  std::cout << std::endl;
  std::cout << dp[3][3][1][1] << std::endl;
  */

  std::cout << ret << std::endl;

  return 0;
}