Problem p00770 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <bits/stdc++.h>
using namespace std;
#define repl(i, a, n) for (int i = ((int)a); i < ((int)n); i++)
#define rep(i, n) repl(i, 0, n)
#define INF INT_MAX / 3
typedef long long ll;
typedef pair<int, int> P;

bool is_prime[1100001];
int cav[2000][2000];
P mem[2000][2000];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};

P dfs(int i, int j, int maxp) {
  if (cav[i][j] > maxp)
    return P(0, 0);
  if (mem[i][j] != P(-1, -1))
    return mem[i][j];
  P res = P(0, 0);
  if (i + 1 < 2000) {
    res = max(res, dfs(i + 1, j, maxp));
    if (j - 1 >= 0)
      res = max(res, dfs(i + 1, j - 1, maxp));
    if (j + 1 < 2000)
      res = max(res, dfs(i + 1, j + 1, maxp));
  }
  if (is_prime[cav[i][j]]) {
    if (res.first == 0)
      res.second = cav[i][j];
    res.first++;
  }
  return mem[i][j] = res;
}

int main(void) {
  is_prime[0] = is_prime[1] = false;
  for (int i = 2; i <= 1100000; i++)
    is_prime[i] = true;
  for (int i = 2; i <= 1100000; i++) {
    if (is_prime[i]) {
      for (int j = i * 2; j <= 1100000; j += i)
        is_prime[j] = false;
    }
  }
  rep(i, 2000) rep(j, 2000) cav[i][j] = INF;
  int si = 1000, sj = 1000, len = 1, num = 1, dir = 0;
  while (num <= 1000000) {
    rep(i, len) {
      cav[si][sj] = num++;
      si += dy[dir];
      sj += dx[dir];
    }
    dir = (dir + 1) % 4;
    if (dir == 0 || dir == 2)
      len++;
  }
  while (1) {
    int n, s;
    cin >> n >> s;
    if (n == 0 && s == 0)
      break;
    rep(i, 2000) rep(j, 2000) mem[i][j] = P(-1, -1);
    P res = P(0, 0);
    rep(i, 2000) rep(j, 2000) {
      if (cav[i][j] == s) {
        res = dfs(i, j, n);
        break;
      }
    }
    printf("%d %d\\n", res.first, res.second);
  }
  return 0;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;
#define repl(i, a, n) for (int i = ((int)a); i < ((int)n); i++)
#define rep(i, n) repl(i, 0, n)
#define INF INT_MAX / 3
typedef long long ll;
typedef pair<int, int> P;

bool is_prime[1100001];
int cav[4000][4000];
P mem[4000][4000];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};

P dfs(int i, int j, int maxp) {
  if (cav[i][j] > maxp)
    return P(0, 0);
  if (mem[i][j] != P(-1, -1))
    return mem[i][j];
  P res = P(0, 0);
  if (i + 1 < 4000) {
    res = max(res, dfs(i + 1, j, maxp));
    if (j - 1 >= 0)
      res = max(res, dfs(i + 1, j - 1, maxp));
    if (j + 1 < 4000)
      res = max(res, dfs(i + 1, j + 1, maxp));
  }
  if (is_prime[cav[i][j]]) {
    if (res.first == 0)
      res.second = cav[i][j];
    res.first++;
  }
  return mem[i][j] = res;
}

int main(void) {
  is_prime[0] = is_prime[1] = false;
  for (int i = 2; i <= 1100000; i++)
    is_prime[i] = true;
  for (int i = 2; i <= 1100000; i++) {
    if (is_prime[i]) {
      for (int j = i * 2; j <= 1100000; j += i)
        is_prime[j] = false;
    }
  }
  rep(i, 4000) rep(j, 4000) cav[i][j] = INF;
  int si = 2000, sj = 2000, len = 1, num = 1, dir = 0;
  while (num <= 1000000) {
    rep(i, len) {
      cav[si][sj] = num++;
      si += dy[dir];
      sj += dx[dir];
    }
    dir = (dir + 1) % 4;
    if (dir == 0 || dir == 2)
      len++;
  }
  while (1) {
    int n, s;
    cin >> n >> s;
    if (n == 0 && s == 0)
      break;
    rep(i, 4000) rep(j, 4000) mem[i][j] = P(-1, -1);
    P res = P(0, 0);
    rep(i, 4000) rep(j, 4000) {
      if (cav[i][j] == s) {
        res = dfs(i, j, n);
        break;
      }
    }
    printf("%d %d\\n", res.first, res.second);
  }
  return 0;
}