Problem p03572 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <string.h>
using namespace std;
const int mod = 1e9 + 7;
int n;
int a[410], b[410];
int v[410][410];
int js[410], cnt;
int kuai[410], wz = 1, zs = 2;
int f[410][410][410];
int ya[410];
int yb[410];
signed main() {
  scanf("%lld", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%lld", &a[i]);
    ya[a[i]] = i;
  }
  for (int i = 1; i <= n; i++) {
    scanf("%lld", &b[i]);
    yb[b[i]] = i;
  }
  kuai[0] = 1;
  for (int i = 1; i <= n; i++) {
    kuai[i] = 1ll * wz * 1ll * zs % mod * 1ll * kuai[i - 1] % mod;
    wz += 3;
    zs += 3;
  }
  // C还有i个没选，A选到第K个，B选到第J个
  f[0][1][1] = 1;
  for (int j = 1; j <= n; j++) {
    for (int k = 1; k <= n; k++) {
      for (int i = 0; i <= n / 3; i++) {
        if (!f[i][k][j])
          continue;
        if (yb[a[k]] <= j || ya[b[j]] <= k) {
          if (a[k] == b[j]) {
            /*if(i==0)
            {
                    continue;
            }*/
            f[i - 1][k + 1][j + 1] = (1ll * f[i - 1][k + 1][j + 1] +
                                      1ll * f[i][k][j] * 1ll * i % mod) %
                                     mod;
            continue;
            // 如要打起来，则强行让C选一个,因为和选了什么没有关系，所以剩下的位置随便选
          }
          if (yb[a[k]] <= j) {
            f[i][k + 1][j] = (1ll * f[i][k + 1][j] + 1ll * f[i][k][j]) % mod;
            continue;
          } else {
            f[i][k][j + 1] = (1ll * f[i][k][j + 1] + 1ll * f[i][k][j]) % mod;
            continue;
          }
        }
        f[i + 1][k + 1][j + 1] =
            (1ll * f[i + 1][k + 1][j + 1] + 1ll * f[i][k][j]) %
            mod; // 先不给C位置，等到能安排的时候直接安排C
        if (i > 0) {
          f[i - 1][k + 1][j] =
              (1ll * f[i][k][j] * i % mod + 1ll * f[i - 1][k + 1][j]) % mod;
          f[i - 1][k][j + 1] =
              (1ll * f[i][k][j] * i % mod + 1ll * f[i - 1][k][j + 1]) % mod;
          // 因为选了什么没关系，所以C可以从他两个后面的一个随便选
          if (i > 1)
            f[i - 2][k + 1][j + 1] =
                (1ll * f[i - 2][k + 1][j + 1] -
                 1ll * f[i][k][j] * (1ll * i * (i - 1) % mod) % mod + mod) %
                mod; // 容斥原理
        }
      }
    }
  }
  int summ = 0;
  for (int i = n / 3; i <= n; i++) {
    summ += f[0][i][n + 1];
    summ %= mod;
  }
  for (int i = n / 3; i <= n; i++) {
    summ += f[0][n + 1][i];
    summ %= mod;
  }
  printf("%lld", 1ll * summ * 1ll * kuai[n / 3] % mod);
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <string.h>
using namespace std;
const int mod = 1e9 + 7;
int n;
int a[410], b[410];
int v[410][410];
int js[410], cnt;
int kuai[410], wz = 1, zs = 2;
int f[410][410][410];
int ya[410];
int yb[410];
signed main() {
  scanf("%lld", &n);
  for (int i = 1; i <= n; i++) {
    scanf("%lld", &a[i]);
    ya[a[i]] = i;
  }
  for (int i = 1; i <= n; i++) {
    scanf("%lld", &b[i]);
    yb[b[i]] = i;
  }
  kuai[0] = 1;
  for (int i = 1; i <= n; i++) {
    kuai[i] = 1ll * wz * 1ll * zs % mod * 1ll * kuai[i - 1] % mod;
    wz += 3;
    zs += 3;
  }
  // C还有i个没选，A选到第K个，B选到第J个
  f[0][1][1] = 1;
  for (int j = 1; j <= n; j++) {
    for (int k = 1; k <= n; k++) {
      for (int i = 0; i <= n / 3; i++) {
        if (!f[i][k][j])
          continue;
        if (yb[a[k]] <= j || ya[b[j]] <= k) {
          if (a[k] == b[j]) {
            if (i == 0) {
              continue;
            }
            f[i - 1][k + 1][j + 1] = (1ll * f[i - 1][k + 1][j + 1] +
                                      1ll * f[i][k][j] * 1ll * i % mod) %
                                     mod;
            continue;
            // 如要打起来，则强行让C选一个,因为和选了什么没有关系，所以剩下的位置随便选
          }
          if (yb[a[k]] <= j) {
            f[i][k + 1][j] = (1ll * f[i][k + 1][j] + 1ll * f[i][k][j]) % mod;
            continue;
          } else {
            f[i][k][j + 1] = (1ll * f[i][k][j + 1] + 1ll * f[i][k][j]) % mod;
            continue;
          }
        }
        f[i + 1][k + 1][j + 1] =
            (1ll * f[i + 1][k + 1][j + 1] + 1ll * f[i][k][j]) %
            mod; // 先不给C位置，等到能安排的时候直接安排C
        if (i > 0) {
          f[i - 1][k + 1][j] =
              (1ll * f[i][k][j] * i % mod + 1ll * f[i - 1][k + 1][j]) % mod;
          f[i - 1][k][j + 1] =
              (1ll * f[i][k][j] * i % mod + 1ll * f[i - 1][k][j + 1]) % mod;
          // 因为选了什么没关系，所以C可以从他两个后面的一个随便选
          if (i > 1)
            f[i - 2][k + 1][j + 1] =
                (1ll * f[i - 2][k + 1][j + 1] -
                 1ll * f[i][k][j] * (1ll * i * (i - 1) % mod) % mod + mod) %
                mod; // 容斥原理
        }
      }
    }
  }
  int summ = 0;
  for (int i = n / 3; i <= n; i++) {
    summ += f[0][i][n + 1];
    summ %= mod;
  }
  for (int i = n / 3; i <= n; i++) {
    summ += f[0][n + 1][i];
    summ %= mod;
  }
  printf("%lld", 1ll * summ * 1ll * kuai[n / 3] % mod);
  return 0;
}