Problem p02968 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
#define LL long long
#define LD long double
using namespace std;
const int NN = 400 + 117;
const int MM = 200 + 117;
int read() {
  int fl = 1, x;
  char c;
  for (c = getchar(); (c < '0' || c > '9') && c != '-'; c = getchar())
    ;
  if (c == '-') {
    fl = -1;
    c = getchar();
  }
  for (x = 0; c >= '0' && c <= '9'; c = getchar())
    x = (x << 3) + (x << 1) + c - '0';
  return x * fl;
}
void open() {
  freopen("a.in", "r", stdin);
  // freopen("a.out","w",stdout);
}
void close() {
  fclose(stdin);
  fclose(stdout);
}

int m, n;
int mod;
struct node {
  int l, r;
  int id;
  int v() {
    if (l == -1)
      return r;
    else
      return l;
  }
} a[NN];
bool cmp(node a, node b) {
  if ((a.id < n && b.id < n) || (a.id >= n && b.id >= n)) {
    return a.id > b.id;
  } else
    return a.v() == b.v() ? a.id > b.id : a.v() < b.v();
}
LL dp[2][NN] = {};
LL v(LL x) { return max(x, 0ll); }
LL calc(int x) {
  for (int i = 0; i <= n + 1; ++i)
    dp[0][i] = 0;
  dp[0][0] = 1;
  int now = 0;
  int pre = 0;
  for (int i = 0; i < 2 * n; ++i) {
    now ^= 1;
    for (int j = 0; j <= pre + 1; ++j)
      dp[now][j] = 0;
    if (a[i].l == -1) {
      for (int j = 0; j <= pre; ++j) {
        dp[now][j] = dp[now ^ 1][j] * v(1 + a[i].r - j - i + pre) % mod;
      }
    } else {
      for (int j = 0; j <= pre; ++j) {
        dp[now][j] += dp[now ^ 1][j] * v(1 + a[i].r - (n + pre + x - j));
        dp[now][j] %= mod;
        dp[now][j + 1] += dp[now ^ 1][j] * v(1 + a[i].l - j - i + pre);
        dp[now][j + 1] %= mod;
      }
      ++pre;
    }
  }
  return dp[now][x];
}
int main() {
  open();
  n = read();
  mod = read();
  for (int i = 0; i < 2 * n; ++i) {
    a[i].r = min(2 * n - 1, (int)sqrt(4 * n * n - i * i));
    a[i].id = i;
    if (i >= n)
      a[i].l = -1;
    else
      a[i].l = sqrt(n * n - i * i - 1);
  }
  sort(a, a + 2 * n, cmp);
  LL ans = 0;
  for (int i = 0, sym = 1; i <= n; ++i, sym = -sym) {
    ans += sym * calc(i);
    ans %= mod;
  }
  ans = (ans + mod) % mod;
  printf("%lld\n", ans);
  close();
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
#define LL long long
#define LD long double
using namespace std;
const int NN = 400 + 117;
const int MM = 200 + 117;
int read() {
  int fl = 1, x;
  char c;
  for (c = getchar(); (c < '0' || c > '9') && c != '-'; c = getchar())
    ;
  if (c == '-') {
    fl = -1;
    c = getchar();
  }
  for (x = 0; c >= '0' && c <= '9'; c = getchar())
    x = (x << 3) + (x << 1) + c - '0';
  return x * fl;
}
void open() {
  freopen("a.in", "r", stdin);
  // freopen("a.out","w",stdout);
}
void close() {
  fclose(stdin);
  fclose(stdout);
}

int m, n;
int mod;
struct node {
  int l, r;
  int id;
  int v() {
    if (l == -1)
      return r;
    else
      return l;
  }
} a[NN];
bool cmp(node a, node b) {
  if ((a.id < n && b.id < n) || (a.id >= n && b.id >= n)) {
    return a.id > b.id;
  } else
    return a.v() == b.v() ? a.id > b.id : a.v() < b.v();
}
LL dp[2][NN] = {};
LL v(LL x) { return max(x, 0ll); }
LL calc(int x) {
  for (int i = 0; i <= n + 1; ++i)
    dp[0][i] = 0;
  dp[0][0] = 1;
  int now = 0;
  int pre = 0;
  for (int i = 0; i < 2 * n; ++i) {
    now ^= 1;
    for (int j = 0; j <= pre + 1; ++j)
      dp[now][j] = 0;
    if (a[i].l == -1) {
      for (int j = 0; j <= pre; ++j) {
        dp[now][j] = dp[now ^ 1][j] * v(1 + a[i].r - j - i + pre) % mod;
      }
    } else {
      for (int j = 0; j <= pre; ++j) {
        dp[now][j] += dp[now ^ 1][j] * v(1 + a[i].r - (n + pre + x - j));
        dp[now][j] %= mod;
        dp[now][j + 1] += dp[now ^ 1][j] * v(1 + a[i].l - j - i + pre);
        dp[now][j + 1] %= mod;
      }
      ++pre;
    }
  }
  return dp[now][x];
}
int main() {
  // open();
  n = read();
  mod = read();
  for (int i = 0; i < 2 * n; ++i) {
    a[i].r = min(2 * n - 1, (int)sqrt(4 * n * n - i * i));
    a[i].id = i;
    if (i >= n)
      a[i].l = -1;
    else
      a[i].l = sqrt(n * n - i * i - 1);
  }
  sort(a, a + 2 * n, cmp);
  LL ans = 0;
  for (int i = 0, sym = 1; i <= n; ++i, sym = -sym) {
    ans += sym * calc(i);
    ans %= mod;
  }
  ans = (ans + mod) % mod;
  printf("%lld\n", ans);
  close();
  return 0;
}