Problem p00770 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

template <class T> void debug(T begin, T end) {
  for (T i = begin; i != end; ++i)
    cerr << *i << " ";
  cerr << endl;
}
inline bool valid(int x, int y, int W, int H) {
  return (x >= 0 && y >= 0 && x < W && y < H);
}

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, -1, 0, 1, 1, 1, -1, -1};
const int L = 5000;
const int N = 1000000;
int grid[L][L];
void init() {
  int l = 1;
  int x = L / 2;
  int y = L / 2;
  int r = 0;
  int rest = 1;
  for (int y = 0; y < L; y++) {
    for (int x = 0; x < L; x++) {
      grid[y][x] = INF;
    }
  }
  for (int i = 1; i <= N; i++) {
    assert(grid[y][x] == INF);
    grid[y][x] = i;
    x += dx[r];
    y += dy[r];
    rest--;
    if (rest == 0) {
      r = (r + 1) % 4;
      if (r % 2 == 0)
        l++;
      rest = l;
    }
  }
}

bool prime[N + 1] = {};
void make_prime() {
  for (int i = 2; i <= N; i++)
    prime[i] = true;
  for (int i = 2; i <= N; i++)
    if (prime[i]) {
      for (int j = 2 * i; j <= N; j += i) {
        prime[j] = false;
      }
    }
}

int main() {
  init();
  make_prime();
  int max_n, st;
  while (cin >> max_n >> st && max_n) {
    static int dp[L][L];
    for (int y = 0; y < L; y++) {
      for (int x = 0; x < L; x++) {
        if (grid[y][x] == st)
          dp[y][x] = prime[grid[y][x]];
        else
          dp[y][x] = -INF;
      }
    }
    int ans1 = 0;
    int ans2 = 0;
    for (int y = 1; y < L; y++) {
      for (int x = 0; x < L; x++)
        if (grid[y][x] <= max_n) {
          for (int dx = -1; dx <= 1; dx++)
            if (x + dx >= 0 && x + dx < L) {
              dp[y][x] = max(dp[y][x], dp[y - 1][x + dx] + prime[grid[y][x]]);
              if (dp[y][x] > ans1 && dp[y][x] > 0 && prime[grid[y][x]]) {
                ans1 = dp[y][x];
                ans2 = grid[y][x];
              } else if (dp[y][x] == ans1 && dp[y][x] > 0 &&
                         prime[grid[y][x]]) {
                ans2 = max(ans2, grid[y][x]);
              }
            }
        }
    }
    printf("%d %d\n", ans1, ans2);
  }
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>

using namespace std;

#define FOR(i, k, n) for (int i = (k); i < (int)(n); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORIT(i, c)                                                            \
  for (__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)

template <class T> void debug(T begin, T end) {
  for (T i = begin; i != end; ++i)
    cerr << *i << " ";
  cerr << endl;
}
inline bool valid(int x, int y, int W, int H) {
  return (x >= 0 && y >= 0 && x < W && y < H);
}

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, -1, 0, 1, 1, 1, -1, -1};
const int L = 3500;
const int N = 1000000;
int grid[L][L];
void init() {
  int l = 1;
  int x = L / 2;
  int y = L / 2;
  int r = 0;
  int rest = 1;
  for (int y = 0; y < L; y++) {
    for (int x = 0; x < L; x++) {
      grid[y][x] = INF;
    }
  }
  for (int i = 1; i <= N; i++) {
    assert(grid[y][x] == INF);
    grid[y][x] = i;
    x += dx[r];
    y += dy[r];
    rest--;
    if (rest == 0) {
      r = (r + 1) % 4;
      if (r % 2 == 0)
        l++;
      rest = l;
    }
  }
}

bool prime[N + 1] = {};
void make_prime() {
  for (int i = 2; i <= N; i++)
    prime[i] = true;
  for (int i = 2; i <= N; i++)
    if (prime[i]) {
      for (int j = 2 * i; j <= N; j += i) {
        prime[j] = false;
      }
    }
}

int main() {
  init();
  make_prime();
  int max_n, st;
  while (cin >> max_n >> st && max_n) {
    static int dp[L][L];
    for (int y = 0; y < L; y++) {
      for (int x = 0; x < L; x++) {
        if (grid[y][x] == st)
          dp[y][x] = prime[grid[y][x]];
        else
          dp[y][x] = -INF;
      }
    }
    int ans1 = 0;
    int ans2 = 0;
    for (int y = 1; y < L; y++) {
      for (int x = 0; x < L; x++)
        if (grid[y][x] <= max_n) {
          for (int dx = -1; dx <= 1; dx++)
            if (x + dx >= 0 && x + dx < L) {
              dp[y][x] = max(dp[y][x], dp[y - 1][x + dx] + prime[grid[y][x]]);
              if (dp[y][x] > ans1 && dp[y][x] > 0 && prime[grid[y][x]]) {
                ans1 = dp[y][x];
                ans2 = grid[y][x];
              } else if (dp[y][x] == ans1 && dp[y][x] > 0 &&
                         prime[grid[y][x]]) {
                ans2 = max(ans2, grid[y][x]);
              }
            }
        }
    }
    printf("%d %d\n", ans1, ans2);
  }
  return 0;
}