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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

const int MAXN = 2001024;

// 結果を格納する変数
int prime[MAXN];     // n 以下の素数のうち i 番目の素数
bool is_prime[MAXN]; // 整数 i が素数であるかどうか

int sieve(int n) {
  int res = 0;
  fill(is_prime, is_prime + MAXN, true);
  is_prime[0] = is_prime[1] = false; // 0 と 1 は素数ではない。
  for (int i = 2; i <= n; ++i) {
    if (!is_prime[i])
      continue;
    prime[res++] = i;
    for (int j = 2 * i; j <= n; j += i)
      is_prime[j] = false; // 素数 i の倍数は素数ではない (ふるい(篩)にかける)
  }
  return res;
}

signed main() {

  sieve(MAXN - 1);
  vector<vector<int>> g(2000, vector<int>(2000));
  vector<pair<int, int>> toC(2000 * 2000);
  int delta = 1000;
  int num = 2;
  int i = 0;
  int j = 0;
  g[i + delta][j + delta] = 1;
  toC[1] = {i + delta, j + delta};
  int step = 1;
  int max_i = 0;
  int max_j = 0;
  int min_i = 0;
  int min_j = 0;

  while (num <= 2000000) {

    // 右に step
    for (int h = 0; h < step; h++) {
      j++;
      g[i + delta][j + delta] = num;
      toC[num] = {i + delta, j + delta};
      num++;
      min_j = min(min_j, j);
      max_j = max(max_j, j);
    }

    // 上に step
    for (int h = 0; h < step; h++) {
      i--;
      g[i + delta][j + delta] = num;
      toC[num] = {i + delta, j + delta};
      num++;
      min_i = min(min_i, i);
      max_i = max(max_i, i);
    }

    step++;

    // 左に step
    for (int h = 0; h < step; h++) {
      j--;
      g[i + delta][j + delta] = num;
      toC[num] = {i + delta, j + delta};
      num++;
      min_j = min(min_j, j);
      max_j = max(max_j, j);
    }

    // 下に step
    for (int h = 0; h < step; h++) {
      i++;
      g[i + delta][j + delta] = num;
      toC[num] = {i + delta, j + delta};
      num++;
      min_i = min(min_i, i);
      max_i = max(max_i, i);
    }
    step++;
  }

  while (1) {

    int m, n;
    cin >> m >> n;
    if (m == 0 && n == 0)
      break;

    int si = toC[n].first;
    int sj = toC[n].second;

    vector<vector<int>> dp(2000, vector<int>(2000, -1));
    dp[si][sj] = is_prime[n];

    int ans = 0;
    int ansval = 0;

    for (int i = 0; i < 1999; i++) {
      for (int j = 1; j < 1998; j++) {

        if (dp[i][j] == -1)
          continue;
        int val = g[i][j];
        if (val > m)
          continue;
        if ((ans < dp[i][j] || (ans == dp[i][j] && ansval < val)) &&
            is_prime[val]) {
          ans = dp[i][j];
          ansval = val;
        }

        int ni = i + 1;
        for (int h = -1; h <= 1; h++) {
          int nj = j + h;
          int nnum = g[ni][nj];
          dp[ni][nj] = max(dp[ni][nj], dp[i][j] + is_prime[nnum]);
        }
      }
    }

    /*
    for(int i = -3; i <= 3; i++){
        for(int j = -3; j <= 3; j++){
            cerr << dp[i + delta][j + delta] << " ";
        }
        cerr << endl;
    }

    */

    cout << ans << " " << ansval << endl;
  }

  return 0;
}


Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

int main() {

  // エラトステネスの篩
  vector<bool> prime(1000010, true); // 1000000までで、素数ならtrue
  prime[0] = prime[1] = false;
  for (int i = 2; i < 1000010; i++) {
    if (prime[i] == true) {
      for (int j = 2 * i; j < 1000010; j += i) {
        prime[j] = false;
      }
    }
  }

  map<pair<int, int>, int> M;
  map<int, pair<int, int>> _M;
  int num = 1;
  int T = 1;
  M[{0, 0}] = num;
  _M[num] = {0, 0};
  num++;
  int i = 0;
  int j = 0;

  while (num < 1000010) {

    j++;
    M[{i, j}] = num;
    _M[num] = {i, j};
    num++;
    for (int r = 0; r < T; r++) {
      i--;
      M[{i, j}] = num;
      _M[num] = {i, j};
      num++;
    }

    j--;
    M[{i, j}] = num;
    _M[num] = {i, j};

    num++;
    for (int r = 0; r < T; r++) {
      j--;
      M[{i, j}] = num;
      _M[num] = {i, j};
      num++;
    }

    i++;
    M[{i, j}] = num;
    _M[num] = {i, j};

    num++;
    for (int r = 0; r < T; r++) {
      i++;
      M[{i, j}] = num;
      _M[num] = {i, j};

      num++;
    }

    j++;
    M[{i, j}] = num;
    _M[num] = {i, j};

    num++;
    for (int r = 0; r < T; r++) {
      j++;
      M[{i, j}] = num;
      _M[num] = {i, j};

      num++;
    }

    T += 2;
  }

  /*for(int i = -10; i <= 10; i++){
      for(int j = -10; j <= 10; j++){
          printf("%.2d ", M[{i, j}]);
      }
      cout << endl;
  }*/

  while (1) {
    int m, n;
    cin >> m >> n;
    if (n == 0)
      break;

    // 幅優先
    map<pair<int, int>, int> dp;
    queue<pair<int, int>> que;
    int si = _M[n].first;
    int sj = _M[n].second;
    que.push({si, sj});
    dp[{si, sj}] = prime[n] ? 1 : 0;

    int ans1 = 0;
    int ans2 = 0;

    while (!que.empty()) {

      int i = que.front().first;
      int j = que.front().second;
      // cout << i << " " << j << " " << dp[{i, j}] << endl;
      if (dp[{i, j}] >= ans1 && prime[M[{i, j}]]) {
        ans1 = dp[{i, j}];
        ans2 = M[{i, j}];
      }

      que.pop();

      int ni = i + 1;
      // 3つ

      for (int dj = -1; dj <= 1; dj++) {
        int nj = j + dj;
        int next_num = M[{ni, nj}];
        if (next_num > m || next_num == 0)
          continue;

        int v = dp[{i, j}] + ((prime[next_num]) ? 1 : 0);
        if (dp.find({ni, nj}) == dp.end() || v > dp[{ni, nj}]) {
          dp[{ni, nj}] = v;
          que.push({ni, nj});
        }
      }
    }

    cout << ans1 << " " << ans2 << endl;
  }
  return 0;
}