Problem:
Prime Caves
An international expedition discovered abandoned Buddhist cave temples
in a giant cliff standing on the middle of a desert.  There were many
small caves dug into halfway down the vertical cliff, which were
aligned on square grids.  The archaeologists in the expedition were
excited by Buddha's statues in those caves.  More excitingly, there
were scrolls of Buddhism sutras (holy books) hidden in some of the caves.  Those
scrolls, which estimated to be written more than
thousand years ago, were of immeasurable value.
The leader of the expedition wanted to collect as many scrolls as
possible.  However, it was not easy to get into the caves as they were
located in the middle of the cliff.  The only way to enter a cave was to
hang you from a helicopter.  Once entered and explored a cave, you can
climb down to one of the three caves under your cave; i.e., either the
cave directly below your cave, the caves one left or right to the cave
directly below your cave.  This can be repeated for as many times as
you want, and then you can descent down to the ground by using a long rope.
So you can explore several caves in one attempt.  But which caves
you should visit?  By examining the results of the preliminary
attempts, a mathematician member of the expedition discovered
that (1) the caves can be numbered from the central one, spiraling
out as shown in Figure D-1; and (2) only those caves with their cave
numbers being prime (let's call such caves
prime caves
),
which are circled in the figure, store scrolls.  From the next
attempt, you would be able to maximize the number of prime caves to
explore.
Figure D-1: Numbering of the caves and the prime caves
Write a program, given the total number of the caves and the cave visited first, that finds the descending route containing the maximum number of prime caves.
Input
The input consists of multiple datasets.  Each dataset has an
  integer
m
(1 ≤
m
≤ 10
6
) and an integer
n
(1 ≤
n
≤
m
) in one line, separated by a space.
m
represents the total number of caves.
n
represents the cave number of the cave from which you will start your exploration.  The last
  dataset is followed by a line with two zeros.
Output
For each dataset, find the path that starts from the cave
n
and
contains the largest number of prime caves, and output the number of
the prime caves on the path and the last prime cave number on the
path in one line, separated by a space.  The cave
n
, explored first, is included
in the caves on the path.
If there is more than one such path, output for the path
in which the last of the prime caves explored has the largest number among such paths.
When there is no such path that explores prime caves, output "
0
0
" (without quotation marks).
Sample Input
49 22
46 37
42 23
945 561
1081 681
1056 452
1042 862
973 677
1000000 1000000
0 0
Output for the Sample Input
0 0
6 43
1 23
20 829
18 947
10 947
13 947
23 947
534 993541

Submitted solutions:

code_snippet: #include "bits/stdc++.h"

#define REP(i,n) for(ll i=0;i<n;++i)
#define RREP(i,n) for(ll i=n-1;i>=0;--i)
#define FOR(i,m,n) for(ll i=m;i<n;++i)
#define RFOR(i,m,n) for(ll i=n-1;i>=m;--i)
#define ALL(v) (v).begin(),(v).end()
#define PB(a) push_back(a)
#define UNIQUE(v) v.erase(unique(ALL(v)),v.end());
#define DUMP(v) REP(aa, (v).size()) { cout << v[a]; if (a != v.size() - 1)cout << " "; else cout << endl; }
#define INF 1000000001ll
#define MOD 1000000007ll
#define EPS 1e-9

const int dx[8] = { 1,1,0,-1,-1,-1,0,1 };
const int dy[8] = { 0,1,1,1,0,-1,-1,-1 };


using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll max(ll a, int b) { return max(a, ll(b)); }
ll max(int a, ll b) { return max(ll(a), b); }
ll min(ll a, int b) { return min(a, ll(b)); }
ll min(int a, ll b) { return min(ll(a), b); }
///(´・ω・`)(´・ω・`)(´・ω・`)(´・ω・`)(´・ω・`)(´・ω・`)///
int m, n;
vi isprime;
pii dfs(vector<vector<pii>> &dp, vvi &cave, int x, int y) {
	if (cave[y][x] > m)return pii(0, 0);
	if (dp[y][x] != pii(-1, -1))return dp[y][x];
	int dj[] = { -1,0,1 };
	pii ret=pii(0,0);
	REP(k, 3) {
		int nx = x + dj[k];
		ret = max(ret, dfs(dp, cave, nx, y + 1));
	}
	if (isprime[cave[y][x]]) {
		ret.first++;
		if (ret.second == 0)ret.second = cave[y][x];
	}
	return dp[y][x] = ret;
	
}
int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	isprime.resize(1e6+1,1);
	isprime[0] = 0; isprime[1] = 0;
	REP(i, isprime.size()) {
		if (isprime[i]) {
			for (int j = 2; j*i < isprime.size(); ++j) {
				isprime[i*j] = 0;
			}
		}
	}
	vvi cave(2000, vi(2000,0));
	int i = 1000, j = 1001;
	int num = 2;
	cave[1000][1000]= 1;
	REP(k, 1005) {
		if (k % 2 == 0) {
			REP(m, k + 2) {

				cave[i][j] = num;
				num++;
				if (m != k + 1)	i--;
			}
			num--;
			REP(m, k + 2) {
				cave[i][j] = num;
				num++;
				j--;
			}
		}
		else {
			REP(m, k + 2) {
				cave[i][j] = num;
				num++;
				if (m != k + 1)	i++;
			}
			num--;
			REP(m, k + 2) {
				cave[i][j] = num;
				num++;
				j++;
			}
		}
	}
	while (1) {
		
		cin >> m >> n;
		if (!m)break;
		int sx, sy;
		REP(i, 2000) {
			REP(j, 2000) {
				if (cave[i][j] == n) {
					sx = j, sy = i;
					break;
				}
			}
		}
		vector<vector<pii>> dp(2000,vector<pii> (2000, pii(-1,-1)));
		auto a = dfs(dp, cave, sx, sy);
		cout <<a.first<<" "<<a.second << endl;


	}
	return 0;
}
accuracy: 1
time_ms: 590
memory_kb: 54060
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
bool solve();

using ll = long long;
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()
typedef pair<int, int> pii;
typedef vector<int> vi;
template <class T>
inline bool chmin(T &a, T b) {
  return ((a > b) ? (a = b, 1) : (0));
}
template <class T>
inline bool chmax(T &a, T b) {
  return ((a < b) ? (a = b, 1) : (0));
}

const int ispsz=100+int(1e6);
bool isPrime[ispsz];
int main() {
  for(int i=2;i<ispsz;i++){
    isPrime[i]=1;
  }
  for(int i=2;i<ispsz;i++){
    if(isPrime[i]){
      for(int j=2*i;j<ispsz;j+=i)isPrime[j]=0;
    }
  }

  while (solve());
  return 0;
}

bool solve() {
  int m,n;cin>>m>>n;
  if (n==0) return 0;
  int l=0;
  while(l*l<m)l++;
  if(l%2==0)l++;
  //lxlの正方形
  auto val(vector(l,vi(l,0)));
  const int di4[]={0,-1,0,1};
  const int dj4[]={1,0,-1,0};
  int ci=l/2,cj=l/2;
  int cdir=0;
  vector<pii>place(l*l+1,pii(0,0));
  rep(step,1,m+1){
    val[ci][cj]=step;
    place[step]=pii(ci,cj);
    if(step>1){
      int ndir=(cdir+1)%4;
      if(val[ci+di4[ndir]][cj+dj4[ndir]]==0)cdir=ndir;
    }
    ci+=di4[cdir];
    cj+=dj4[cdir];
  }
  // rep(i,0,l){
  //   rep(j,0,l)printf("%4d",val[i][j]);
  //   printf("\n");
  // }
  vector<pii> dp(l,pii(-100,0));
  ci=place[n].first;
  cj=place[n].second;
  assert(n==val[ci][cj]);
  dp[cj]=pii(0,0);
  if(isPrime[val[ci][cj]])dp[cj]=pii(1,val[ci][cj]);
  
  for(;ci+1<l;ci++){
    vector<pii> old(l,pii(-100,0));
    swap(old,dp);
    rep(j,0,l){
      for(int dj=-1;dj<=1;dj++){
        int nj=j+dj;
        if(nj<0||nj>=l)continue;
        int v=val[ci+1][nj];
        if(isPrime[v]){
          dp[nj]=max(dp[nj],pii(old[j].first+1,v));
        }else{
          dp[nj]=max(dp[nj],pii(old[j].first,old[j].second));
        }
      }
    }
  }

  pii ans=pii(0,0);
  rep(j,0,l)ans=max(ans,dp[j]);
  cout<<ans.first<<" "<<ans.second<<endl;

  return 1;
}
accuracy: 1
time_ms: 10
memory_kb: 16176
final_rank: 1

code_snippet: //#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,n) for (ll i=0;i<(ll)n;i++)
#define rrep(i,n) for (ll i=n-1;i>=(ll)0;i--)
#define loop(i,m,n) for(ll i=m;i<=(ll)n;i++)
#define rloop(i,m,n) for(ll i=m;i>=(ll)n;i--)
#define vl vector<ll>
#define vvl vector<vector<ll>>
#define vdbg(a) rep(ii,a.size()){cout<<a[ii]<<" ";}cout<<endl;
#define vpdbg(a) rep(ii,a.size()){cout<<"{"<<a[ii].first<<","<<a[ii].second<<"} ";}cout<<endl;
#define vvdbg(a) rep(ii,a.size()){rep(jj,a[ii].size()){cout<<a[ii][jj]<<" ";}cout<<endl;}
#define setdbg(a) for(const auto & ii:a){cout<<ii<<" ";}cout<<endl;
#define inf 1e9
#define mod 998244353LL
//#define mod 1000000007LL
#define eps 0.000000001
random_device rnd;// 非決定的な乱数生成器
mt19937 mt(rnd());// メルセンヌ・ツイスタの32ビット版、引数は初期シード

//#include<boost/multiprecision/cpp_int.hpp>
//#define bbi boost::multiprecision::cpp_int
//#include<atcoder/lazysegtree>


//整数同士の累乗の計算をする。
ll power(ll A, ll B) {
	ll result = 1;
	for (ll i=0;i<B;i++){
		result *= A;
	}
	return result;
}

// nのk乗をmodで割った余りを計算
ll power_mod(ll n, ll k){
	long long result = 1;
	while (k > 0){
		if ((k&1) ==1)result=(result*n)%mod;
		n=n*n%mod;
		k >>= 1;
	}
	return result;
}


//受け取った2次元文字の外側に、文字pをコーティングする。
vector<string> pad(vector<string> &s,char p){
	ll h=s.size();
	ll w=s[0].size();
	vector<string> res(h+2,string(w+2,p));
	rep(i,h)rep(j,w)res[i+1][j+1]=s[i][j];
	return res;
}

// Union-Find
struct UnionFind {
	vector<int> par, siz;
	UnionFind(int n) : par(n, -1) , siz(n, 1) { }
	// 根を求める
	int root(int x) {
		if (par[x] == -1) return x;
		else return par[x] = root(par[x]);
	}
	// x と y が同じグループに属するかどうか (根が一致するかどうか)
	bool issame(int x, int y) {
		return root(x) == root(y);
	}
	// x を含むグループと y を含むグループとを併合する
	bool unite(int x, int y) {
		x = root(x), y = root(y);
		if (x == y) return false; 
		if (siz[x] < siz[y]) swap(x, y);
		par[y] = x;
		siz[x] += siz[y];
		return true;
	}
	// x を含むグループのサイズ
	int size(int x) {
		return siz[root(x)];
	}
};


//グリッド問題等用
vl dx={1,0,-1,0};
vl dy={0,1,0,-1};
vvl g(1000001);
vector<bool> e(1000001,true);

ll solve(){
	ll m,n;
	cin>>m>>n;
	if(m==0&&n==0){return 1;}
	
	pair<ll,ll> ans={0,0};
	vl dp(m+1,0);
	queue<ll> qu;
	vector<bool> f(m+1,false);
	qu.push(n);
	while(!qu.empty()){
		ll tmp=qu.front();
		qu.pop();
		
		if(f[tmp])continue;
		f[tmp]=true;

		if(e[tmp]){
			dp[tmp]++;
			ans=max(ans,{dp[tmp],tmp});
		}

		rep(i,g[tmp].size()){
			if(g[tmp][i]>m)continue;
			dp[g[tmp][i]]=max(dp[g[tmp][i]],dp[tmp]);
			qu.push(g[tmp][i]);
		}
	}
	cout<<ans.first<<" "<<ans.second<<endl;
	//vdbg(g[37]);
	return 0;
}

//メイン
int main(){
	
	vvl mp(2000,vl(2000,inf));
	vector<pair<ll,ll>> inv(1010000);
	ll cnt=1;
	pair<ll,ll> zahyou={1000,1000};
	rep(i,inf){
		//右
		rep(j,2*i+1){
			mp[zahyou.first][zahyou.second]=cnt;
			inv[cnt]=zahyou;
			zahyou.first++;
			cnt++;
		}
		//上
		rep(j,2*i+1){
			mp[zahyou.first][zahyou.second]=cnt;
			inv[cnt]=zahyou;
			zahyou.second--;
			cnt++;
		}
		//左
		rep(j,2*i+2){
			mp[zahyou.first][zahyou.second]=cnt;
			inv[cnt]=zahyou;
			zahyou.first--;
			cnt++;
		}
		//下
		rep(j,2*i+2){
			mp[zahyou.first][zahyou.second]=cnt;
			inv[cnt]=zahyou;
			zahyou.second++;
			cnt++;
		}
		if(cnt>1000000)break;
	}

	loop(i,1,1000000){
		pair<ll,ll> xy=inv[i];
		
		xy.second++;
		xy.first--;
		
		rep(j,3){
			//次があるなら
			if(mp[xy.first][xy.second]!=inf){
				g[i].push_back(mp[xy.first][xy.second]);
			}
			xy.first++;
		}
	}
	
	e[0]=false;
	e[1]=false;
	loop(i,2,1000000){
		if(!e[i])continue;
		for(ll j=i*i;j<=1000000;j+=i){
			e[j]=false;
		}
	}

	while(solve()==0);
	return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 128476
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(a) (a).begin(), (a).end()
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rrep(i, n) for (int i = (int)(n); i >= 0; i--)
#define range(i, l, r) for (int i = (int)(l); i < (int)(r); i++)
using ll = long long;

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "[";
    for (int i = 0; i < v.size(); i++) {
        os << v[i] << (i == (v.size() - 1) ? "" : ", ");
    }
    os << "]";
    return os;
}

template <typename T1, typename T2>
ostream& operator<<(ostream& os, const pair<T1, T2> p) {
    os << "{" << p.first << ", " << p.second << "}";
    return os;
}

pair<int, int> enc(int n) {
    if (n == 1) {
        return {0, 0};
    }
    int d = 1;
    n -= 2;
    while (n >= 8 * d) {
        n -= 8 * d;
        d++;
    }

    if (n < 2 * d) {
        return {d, -d + n + 1};
    } else if (n < 4 * d) {
        n -= 2 * d;
        return {d - 1 - n, d};
    } else if (n < 6 * d) {
        n -= 4 * d;
        return {-d, d - 1 - n};
    } else {
        n -= 6 * d;
        return {-d + n + 1, -d};
    }
}

int dec(int i, int j) {
    if (i == 0 && j == 0) return 1;
    int d = max(abs(i), abs(j));
    int base = pow(2 * d - 1, 2);
    if (i == d && j > -d) {
        return base + j + d;
    } else if (j == d) {
        return base + 2 * d + d - i;
    } else if (i == -d) {
        return base + 4 * d + d - j;
    } else {
        return base + 6 * d + i + d;
    }
}

map<int, pair<int, int>> dp, ep;
#include <cassert>

int main() {
    int mx = 1000001;
    vector<int> min_factor(mx, 0);
    rep(i, mx) min_factor[i] = i;
    min_factor[0] = -1;
    min_factor[1] = -1;
    range(i, 2, mx) {
        if (min_factor[i] != i) continue;
        int j = i;
        while (j < mx) {
            min_factor[j] = i;
            j += i;
        }
    }

    while (true) {
        int m, n;
        cin >> m >> n;
        if (m == 0) break;
        dp.clear();
        ep.clear();

        pair<int, int> ans;
        if (min_factor[n] == n) {
            dp[n] = {1, n};
            ans = {1, n};
        } else {
            dp[n] = {0, 0};
            ans = {0, 0};
        }

        while (!dp.empty()) {
            ep.clear();
            for (auto [n, p] : dp) {
                auto [i, j] = enc(n);
                int nj = j - 1;
                range(ni, i - 1, i + 2) {
                    int nn = dec(ni, nj);
                    if (nn > m) continue;
                    pair<int, int> val;
                    if (min_factor[nn] == nn) {
                        val = {p.first + 1, nn};
                    } else {
                        val = p;
                    }
                    ans = max(ans, val);
                    if (ep.find(nn) == ep.end()) {
                        ep[nn] = val;
                    } else {
                        ep[nn] = max(ep[nn], val);
                    }
                }
            }
            swap(ep, dp);
        }
        cout << ans.first << " " << ans.second << endl;
    }
}
accuracy: 1
time_ms: 130
memory_kb: 7100
final_rank: 2

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;

int w = 1100;

vector<int> dx = {-1, 0, 1, 0};
vector<int> dy = {0, 1, 0, -1};
const int INF = 2e9;

vector<bool> sieve(int n)
{
    vector<bool> is_prime(n + 1);
    for (int i = 0; i <= n; i++) is_prime[i] = true;
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i <= n; i++) {
        if (is_prime[i]) {
            for (int j = 2 * i; j <= n; j += i) is_prime[j] = false;
        }
    }
    return is_prime;
}

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

        vector<vector<int>> grid(w, vector<int>(w, 0));
        vector<pair<int, int>> ma(m + 1);

        int dir = 2;
        int cur = 1, row = w / 2, col = w / 2;

        int mr = 0, mc = 0;
        while (true) {
            if (cur > m) break;

            grid[row][col] = cur;
            ma[cur] = {row, col};
            mr = max(mr, row);
            mc = max(mc, col);
            cur++;

            int nx = row + dx[(dir - 1 + 4) % 4];
            int ny = col + dy[(dir - 1 + 4) % 4];
            if (grid[nx][ny] == 0) { dir = (dir - 1 + 4) % 4; }

            row = row + dx[dir], col = col + dy[dir];
        }

        // for (int i = 5;i < 15;i++) {
        //     for (int j = 5;j < 15;j++) {
        //         cout << grid[i][j] << " ";
        //     }
        //     cout << endl;
        // }

        auto is_prime = sieve(m + 1);
        vector<vector<int>> dp(w, vector<int>(w, -1));
        vector<vector<int>> lprime(w, vector<int>(w, 0));

        auto& [sr, sc] = ma[n];
        dp[sr][sc] = is_prime[grid[sr][sc]];
        lprime[sr][sc] = (is_prime[grid[sr][sc]] ? n : 0);

        for (int i = sr; i < mr; i++) {
            for (int j = 0; j < w; j++) {
                if (dp[i][j] != -1) {
                    if (dp[i + 1][j] < dp[i][j] + is_prime[grid[i + 1][j]]) {
                        dp[i + 1][j] = max(dp[i + 1][j],dp[i][j] + is_prime[grid[i + 1][j]]);
                        lprime[i + 1][j] = (is_prime[grid[i + 1][j]] ? grid[i + 1][j]: lprime[i][j]);
                    }
                }
                if (j - 1 >= 0 && dp[i][j - 1] != -1) {
                    if (dp[i + 1][j] < dp[i][j - 1] + is_prime[grid[i + 1][j]]) {
                        dp[i + 1][j] = max(dp[i + 1][j],dp[i][j - 1] + is_prime[grid[i + 1][j]]);
                        lprime[i + 1][j] = (is_prime[grid[i + 1][j]] ? grid[i + 1][j]:lprime[i][j - 1]);
                    }
                }
                if (j + 1 < w && dp[i][j + 1] != -1) {
                    if (dp[i + 1][j] < dp[i][j + 1] + is_prime[grid[i + 1][j]]) {
                        dp[i + 1][j] = dp[i][j + 1] + is_prime[grid[i + 1][j]];
                        lprime[i + 1][j] = (is_prime[grid[i + 1][j]] ? grid[i + 1][j]: lprime[i][j + 1]);
                    }
                }
            }
        }

        // cout << endl;
        // for (int i = 5;i < 15;i++) {
        //     for (int j = 5;j < 15;j++) {
        //         cout << dp[i][j] << " ";
        //     }
        //     cout << endl;
        // }

        int ans = 0;
        int lp = 0;
        for (int j = 0; j < w; j++) {
            if (ans < dp[mr][j]) {
                ans = dp[mr][j];
                lp = lprime[mr][j];
            }else if (ans == dp[mr][j]) {
                if (lp < lprime[mr][j]) {
                    lp = lprime[mr][j];
                }
            }
        }
        cout << ans << " " << lp << endl;
    }
}
accuracy: 1
time_ms: 140
memory_kb: 25596
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<long long, long long>;
#define rep(i, a, b) for(long long i = (a); i < (b); ++i)
#define rrep(i, a, b) for(long long i = (a); i >= (b); --i)
constexpr long long inf = 4e18;
struct SetupIO {
    SetupIO() {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout << fixed << setprecision(30);
    }
} setup_io;
struct EratosthenesSieve {
    vector<int> primes, min_factor, moebius, euler;
    EratosthenesSieve(const int n)
        : primes(), min_factor(n + 1), moebius(n + 1, 1), euler(n + 1) {
        assert(n >= 1);
        iota(min_factor.begin(), min_factor.end(), 0);
        min_factor[0] = min_factor[1] = -1;
        iota(euler.begin(), euler.end(), 0);
        for(int i = 2; i <= n; ++i) {
            if(min_factor[i] < i) continue;
            primes.emplace_back(i);
            moebius[i] = -1;
            euler[i] = euler[i] / i * (i - 1);
            for(int j = i * 2; j <= n; j += i) {
                if(min_factor[j] == j) min_factor[j] = i;
                if((j / i) % i == 0) moebius[j] = 0;
                else moebius[j] = -moebius[j];
                euler[j] = euler[j] / i * (i - 1);
            }
        }
    }
};
int main(void) {
    constexpr int sz = 1001;
    vector<vector<int>> num(sz, vector<int>(sz));
    int i = sz / 2, j = sz / 2, cur = 1;
    rep(k, 1, inf) {
        rep(_, 0, k) {
            num[i][j] = cur++;
            if(k % 2 == 1) j++;
            else j--;
        }
        if(cur > sz * sz) break;
        rep(_, 0, k) {
            num[i][j] = cur++;
            if(k % 2 == 1) i--;
            else i++;
        }
    }
    EratosthenesSieve sieve(sz * sz + 1);
    while(1) {
        int m, n;
        cin >> m >> n;
        if(m == 0 and n == 0) break;
        int si = -1, sj = -1;
        rep(i, 0, sz) {
            rep(j, 0, sz) {
                if(num[i][j] == n) {
                    si = i;
                    sj = j;
                }
            }
        }
        assert(si != -1 and sj != -1);
        vector<vector<pair<int, int>>> dp(sz, vector<pair<int, int>>(sz, {-1, -1}));
        dp[si][sj].first = sieve.min_factor[num[si][sj]] == num[si][sj];
        if(dp[si][sj].first == 0) dp[si][sj].second = 0;
        else dp[si][sj].second = num[si][sj];
        queue<pair<int, int>> que;
        que.push({si, sj});
        while(!que.empty()) {
            auto [i, j] = que.front();
            que.pop();
            rep(dj, -1, 2) {
                int ni = i + 1, nj = j + dj;
                if(0 <= ni and ni < sz and 0 <= nj and nj < sz and num[ni][nj] <= m) {
                    if(dp[ni][nj].first == -1) que.push({ni, nj});
                    if(dp[i][j].first + (sieve.min_factor[num[ni][nj]] == num[ni][nj]) > dp[ni][nj].first) {
                        dp[ni][nj] = {dp[i][j].first + (sieve.min_factor[num[ni][nj]] == num[ni][nj]), dp[i][j].second};
                        if(sieve.min_factor[num[ni][nj]] == num[ni][nj]) {
                            dp[ni][nj].second = num[ni][nj];
                        }
                    } else if(dp[i][j].first + (sieve.min_factor[num[ni][nj]] == num[ni][nj]) == dp[ni][nj].first and dp[i][j].second > dp[ni][nj].second) {
                        dp[ni][nj] = {dp[i][j].first + (sieve.min_factor[num[ni][nj]] == num[ni][nj]), dp[i][j].second};
                        if(sieve.min_factor[num[ni][nj]] == num[ni][nj]) {
                            dp[ni][nj].second = num[ni][nj];
                        }
                    }
                }
            }
        }
        pair<int, int> ans = {0, 0};
        rep(i, 0, sz) rep(j, 0, sz) ans = max(ans, dp[i][j]);
        cout << ans.first << ' ' << ans.second << '\n';
    }
}
accuracy: 1
time_ms: 150
memory_kb: 27276
final_rank: 8

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

const int dx[4] = {0, -1, 0, 1};
const int dy[4] = {1, 0, -1, 0};
bool isprime[1 << 20];
int cell[1209][1209];
pair<int, int> dp[1209][1209];

void Initialize() {
	for (int i = 2; i <= 1000000; i++) isprime[i] = true;
	for (int i = 2; i <= 1000000; i++) {
		for (int j = 2 * i; j <= 1000000; j += i) isprime[j] = false;
	}
}

pair<int, int> update(pair<int, int> initial, int pos) {
	if (isprime[pos] == false) return initial;
	return make_pair(initial.first + 1, pos);
}

pair<int, int> solve(int Num, int First) {
	for (int i = 0; i <= 1200; i++) {
		for (int j = 0; j <= 1200; j++) cell[i][j] = -1;
		for (int j = 0; j <= 1200; j++) dp[i][j] = make_pair(-1000000, -1000000);
	}

	// Get Cell
	int sx = 600;
	int sy = 600;
	int dir = 0;
	for (int i = 1; i <= Num; i++) {
		cell[sx][sy] = i;
		if (i == First) dp[sx][sy] = update(make_pair(0, 0), First);
		sx += dx[dir];
		sy += dy[dir];
		if (dir != 0) {
			if (abs(sx - 600) == abs(sy - 600)) dir = (dir + 1) % 4;
		}
		else {
			if (abs(sx - 600) + 1 == abs(sy - 600)) dir = (dir + 1) % 4;
		}
	}

	// Dynamic Programming
	pair<int, int> Answer = make_pair(0, 0);
	for (int i = 1; i <= 1199; i++) {
		for (int j = 1; j <= 1199; j++) {
			if (cell[i][j] == -1) continue;
			pair<int, int> v = max({dp[i - 1][j - 1], dp[i - 1][j], dp[i - 1][j + 1]});
			dp[i][j] = max(dp[i][j], update(v, cell[i][j]));
			Answer = max(Answer, dp[i][j]);
		}
	}

	// Return
	return Answer;
}

int main() {
	Initialize();
	while (true) {
		int Num, First; cin >> Num >> First;
		if (Num == 0 && First == 0) break;
		pair<int, int> Answer = solve(Num, First);
		cout << Answer.first << " " << Answer.second << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 21384
final_rank: 4

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

const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};
bool isprime[1 << 20];
int cell[1209][1209];
pair<int, int> dp[1209][1209];

void Initialize() {
	for (int i = 2; i <= 1000000; i++) isprime[i] = true;
	for (int i = 2; i <= 1000000; i++) {
		for (int j = 2 * i; j <= 1000000; j += i) isprime[j] = false;
	}
}

pair<int, int> Solve(int Num, int Fst) {
	for (int i = 0; i <= 1200; i++) {
		for (int j = 0; j <= 1200; j++) cell[i][j] = -1;
	}
	cell[600][600] = 1;
	int sx = 600;
	int sy = 601;
	int dir = 0;
	for (int i = 2; i <= Num; i++) {
		cell[sx][sy] = i;
		sx += dx[dir];
		sy += dy[dir];
		if (dir != 3) {
			if (abs(sx - 600) == abs(sy - 600)) dir = (dir + 1) % 4;
		}
		else {
			if (abs(sx - 600) + 1 == abs(sy - 600)) dir = (dir + 1) % 4;
		}
	}

	// Dynamic Programming
	pair<int, int> Answer = make_pair(0, 0);
	for (int i = 0; i <= 1200; i++) {
		for (int j = 0; j <= 1200; j++) {
			dp[i][j] = make_pair(-1000000, -1000000);
			if (cell[i][j] == Fst) {
				if (isprime[Fst] == true) dp[i][j] = make_pair(1, Fst);
				else dp[i][j] = make_pair(0, 0);
			}
		}
	}
	for (int i = 1; i <= 1199; i++) {
		for (int j = 1; j <= 1199; j++) {
			Answer = max(Answer, dp[i][j]);
			if (cell[i + 1][j - 1] != -1) {
				pair<int, int> nex = dp[i][j];
				if (isprime[cell[i + 1][j - 1]] == true) { nex.first += 1; nex.second = cell[i + 1][j - 1]; }
				dp[i + 1][j - 1] = max(dp[i + 1][j - 1], nex);
			}
			if (cell[i + 1][j] != -1) {
				pair<int, int> nex = dp[i][j];
				if (isprime[cell[i + 1][j]] == true) { nex.first += 1; nex.second = cell[i + 1][j]; }
				dp[i + 1][j] = max(dp[i + 1][j], nex);
			}
			if (cell[i + 1][j + 1] != -1) {
				pair<int, int> nex = dp[i][j];
				if (isprime[cell[i + 1][j + 1]] == true) { nex.first += 1; nex.second = cell[i + 1][j + 1]; }
				dp[i + 1][j + 1] = max(dp[i + 1][j + 1], nex);
			}
		}
	}

	// Return
	return Answer;
}

int main() {
	Initialize();
	while (true) {
		int Num, First; cin >> Num >> First;
		if (Num == 0 && First == 0) break;
		pair<int, int> Answer = Solve(Num, First);
		cout << Answer.first << " " << Answer.second << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 21508
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};

int main() {
    bool Prime[1000001] = {};
    rep(i,0,1000001) Prime[i] = true;
    Prime[0] = Prime[1] = false;
    rep(i,2,1000001) {
        if (Prime[i]) {
            for (int j = 2; i * j <= 1000000; j++) {
                Prime[i*j] = false;
            }
        }
    }
    int MAXS = 1010;
    int Cave[MAXS][MAXS] = {};
    int X = MAXS/2, Y = MAXS/2, P = 1;
    Cave[X][Y] = P;
    rep(i,0,3000) {
        int dir = i % 4;
        rep(j,0,(i+2)/2) {
            X += dx[dir], Y += dy[dir], P++;
            if (P > 1000000) break;
            Cave[X][Y] = P;
        }
        if (P > 1000000) break;
    }
while(1) {
    int N, M;
    cin >> N >> M;
    if (N == 0 && M == 0) return 0;
    vector<vector<int>> ANS(MAXS, vector<int>(MAXS,-inf));
    rep(i,0,MAXS) {
        rep(j,0,MAXS) {
            if (Cave[i][j] == M) {
                ANS[i][j] = 0;
            }
        }
    }
    rrep(j,0,MAXS-1) {
        rep(i,1,MAXS-1) {
            if (Cave[i][j] == 0 || N < Cave[i][j]) continue;
            chmax(ANS[i][j], ANS[i-1][j+1]);
            chmax(ANS[i][j], ANS[i][j+1]);
            chmax(ANS[i][j], ANS[i+1][j+1]);
            if (Prime[Cave[i][j]]) ANS[i][j]++;
        }
    }
    int ANSX = 0, ANSY = 0;
    rep(i,0,MAXS) {
        rep(j,0,MAXS) {
            if (ANS[i][j] <= 0) continue;
            if (!Prime[Cave[i][j]]) continue;
            if (ANS[i][j] > ANSX) ANSX = ANS[i][j], ANSY = Cave[i][j];
            else if (ANS[i][j] == ANSX) chmax(ANSY, Cave[i][j]);
        }
    }
    cout << ANSX << ' ' << ANSY << endl;
}
}
accuracy: 1
time_ms: 100
memory_kb: 12476
final_rank: 3

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
using namespace std;

using ll = long long;
using i64 = long long;
using pll = pair<ll,ll>;
using plll = pair<pll,ll>;
using pii =pair<int,int>;

constexpr ll mod = 998244353;

int dx[4]={0,-1,0,1};
int dy[4]={1,0,-1,0};

int dX[4]={0,-1,0,1};
int dY[4]={1,0,-1,0};

//library


//end





int main(){
    int max_n=1000005;
    vector<int> A(max_n,-1);


    for (int i=2; i<max_n; i++){
        if (A[i]==-1){
            for (int s=2; s<max_n; s++){
                if (i*s>=max_n)break;
                if (A[i*s]==-1)A[i*s]=i;
            }
        }
    }

    int N=1100;
    vector<vector<int>>F(N,vector<int>(N,0));
    vector<vector<int>>num(N,vector<int>(N,0));
    map<int,pii> invnow;
    int x=550, y=550,now=1;
    num[x][y]=1;
    invnow[now]=make_pair(x,y);

    int len=0;
    for (int i=0; i<2000; i++){
        if (i%2==0)len++;
        int d=i%4;
        for (int j=0; j<len; j++){
            x=x+dx[d];
            y=y+dy[d];
            now++;
            num[x][y]=now;
            invnow[now]=make_pair(x,y);
            if (now>=max_n) goto end;
            if (A[now]==-1)F[x][y]=1;
        }
    }

    end:;



    while (true){
        int m,n;
        cin>>m>>n;
        if (m==0)break;
        vector<vector<pii>> dp(N,vector<pii>(N,make_pair(-1,-1)));
        auto [x,y]=invnow[n];
        dp[x][y]=make_pair(0,-1);
        if (F[x][y]) dp[x][y]=make_pair(1,n);
        queue<int> que;
        que.push(n);

        pii ans=make_pair(0,0);
        set<int> dist;
        while (que.size()>0){
            n=que.front();
            //cout<<n<<' ';
            que.pop();
            if (dist.count(n)>0)continue;
            dist.insert(n);
            auto [x,y]=invnow[n];
            if (ans.first<dp[x][y].first){
                ans=dp[x][y];
            }
            if (ans.first==dp[x][y].first && ans.second<dp[x][y].second){
                ans=dp[x][y];
            }


            for (int d=-1; d<2; d++){
                int nx=x+1, ny=y+d;
                if (nx>=num.size() || ny<0)continue;
                if (num[nx][ny]>m)continue;

                int f=F[nx][ny], pre=dp[x][y].second;
                if (f>0)pre=num[nx][ny];

                if (dp[nx][ny].first<dp[x][y].first+f){
                    dp[nx][ny]=make_pair(dp[x][y].first+f, pre);
                    que.push(num[nx][ny]);
                }
                if (dp[nx][ny].first==dp[x][y].first+f && dp[nx][ny].second<pre){
                    dp[nx][ny]=make_pair(dp[x][y].first+f, pre);
                    que.push(num[nx][ny]);
                }
            }

        }

        cout<<ans.first<<' '<<ans.second<<endl;




    }

}
accuracy: 1
time_ms: 600
memory_kb: 116760
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (long long i = 0; i < (long long)(n); i++)
#define rrep(i,start,end) for (long long i = start;i >= (long long)(end);i--)
#define repn(i,end) for(long long i = 0; i <= (long long)(end); i++)
#define reps(i,start,end) for(long long i = start; i < (long long)(end); i++)
#define repsn(i,start,end) for(long long i = start; i <= (long long)(end); i++)
#define each(p,a) for(auto &p:a)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<long long> vll;
typedef vector<pair<long long ,long long>> vpll;
typedef vector<vector<long long>> vvll;
typedef set<ll> sll;
typedef map<long long , long long> mpll;
typedef pair<long long ,long long> pll;
typedef tuple<long long , long long , long long> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (int)x.size()
// << std::fixed << std::setprecision(10)
const int INF = 1LL << 30;
const ld EPS = 1e-9;
 
inline ll lfloor(ll x,ll m){return (x - ((x % m+ m)%m))/m;}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

// for AOJ or ICPC or etc..
// 全部が0だったらtrueを返す
template<class Tp> bool zero (const Tp &x) {return x == 0;}
template<class Tp, class... Args> bool zero (const Tp &x, const Args& ...args) {return zero(x) and zero(args...);}

//https://drken1215.hatenablog.com/entry/2023/05/23/233000
// A^N mod M
template<class T> T pow_mod(T A, T N, T M) {
    T res = 1 % M;
    A %= M;
    while (N) {
        if (N & 1) res = (res * A) % M;
        A = (A * A) % M;
        N >>= 1;
    }
    return res;
}

bool MillerRabin(long long N, vector<long long> A) {
    long long s = 0, d = N - 1;
    while (d % 2 == 0) {
        ++s;
        d >>= 1;
    }
    for (auto a : A) {
        if (N <= a) return true;
        long long t, x = pow_mod<__int128_t>(a, d, N);
        if (x != 1) {
            for (t = 0; t < s; ++t) {
                if (x == N - 1) break;
                x = __int128_t(x) * x % N;
            }
            if (t == s) return false;
        }
    }
    return true;
}

bool is_prime(long long N) {
    if (N <= 1) return false;
    if (N == 2) return true;
    if (N % 2 == 0) return false;
    if (N < 4759123141LL)
        return MillerRabin(N, {2, 7, 61});
    else
        return MillerRabin(N, {2, 325, 9375, 28178, 450775, 9780504, 1795265022});
}

map<pair<int,int>,int> mp;
int lim = lpow(10,6);
vector<vector<int>> g;
vector<int> ord;

void pre(){
  mp[{0,0}] = 1;
  mp[{0,1}] = 0;
  pll lst = {0,1};
  repsn(i,3,lim){
    auto[y,x] = lst;
    ll d = mp[{y,x}];
    if(d == 0){
      //右
      if(!mp.count({y-1,x})){
        lst = {y-1,x};
        mp[{y-1,x}] = 1;
      }else{
        lst = {y,x+1};
        mp[{y,x+1}] = 0;
      }
    }else if(d == 1){
      //上
      if(!mp.count({y,x-1})){
        lst = {y,x-1};
        mp[{y,x-1}] = 2;
      }else{
        lst = {y-1,x};
        mp[{y-1,x}] = 1;
      }
    }else if(d == 2){
        //左
      if(!mp.count({y+1,x})){
        lst = {y+1,x};
        mp[{y+1,x}] = 3;
      }else{
        lst = {y,x-1};
        mp[{y,x-1}] = 2;
      }
    }else{
      //下
      if(!mp.count({y,x+1})){
        lst = {y,x+1};
        mp[{y,x+1}] = 0;
      }else{
        lst = {y+1,x};
        mp[{y+1,x}] = 3;
      }
    }
    mp[{y,x}] = i-1;
  }
  mp[lst] = lim;
  // cerr << "here" << endl;

  g.resize(lim+1);
  each(p,mp){
    auto[y,x] = p.first;
    ll i = p.second;
    if(mp.count({y+1,x+1})){
      g[i].push_back(mp[{y+1,x+1}]);
    }
    if(mp.count({y+1,x})){
      g[i].push_back(mp[{y+1,x}]);
    }
    if(mp.count({y+1,x-1})){
      g[i].push_back(mp[{y+1,x-1}]);
    }
  }
  // cerr <<"here" << endl;
  //隣接リストgを利用,n頂点
  auto topological_sort = [](vector<vector<int>> &g,ll n){
    vector<int> topological_order;
   
    vector<int> in_cnt(n);//入次数
    rep(i,n){
      for(ll p : g[i]){
        in_cnt[p]++;
      }
    }
    queue<int> que;
    //始点入れる
    rep(i,n){
      if(in_cnt[i] == 0){
        que.push(i);
      }
    }
   
    while(!que.empty()){
      ll now  = que.front();
      que.pop();
      topological_order.push_back(now);
      for(ll p :g[now]){
        if(in_cnt[p] > 0){
          in_cnt[p]--;
          if(in_cnt[p] == 0){
            que.push(p);
          }
        }
      }
    }
    return topological_order;
  };
  ord = topological_sort(g,lim+1);
  mp.clear();

}

// 変数をちゃんと全部受け取る！
void solve(ll m,ll n){
  //nから始めるｍ以上は通れない
  vector<pair<int,int>> dp(lim+1,{-INF,-INF});//個数、最後
  dp[n] = {0,0};
  rep(z,lim+1){
    ll i = ord[z];
    if(i > m)continue;
    if(dp[i].first < 0)continue;
    //自分が素数なら追加
    if(is_prime(i)){
      dp[i].first++;
      dp[i].second = i;
    }
    each(p,g[i])if(p <= m){
      if(dp[p].first < dp[i].first){
        dp[p] = dp[i];
      }else if(dp[p].first == dp[i].first){
        if(dp[p].second < dp[i].second){
          dp[p] = dp[i];
        }
      }
    }
  }
  pll ret = *max_element(all(dp));
  if(ret.first < 0){
    cout << 0 << " " << 0 << endl;
  }else{
    cout << ret.first << " " << ret.second << endl;
  }
}
 
int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  pre();
  while(true){
    LL(m,n);//変数数調整
    if(zero(m,n))break;
    solve(m,n);
  }
}
accuracy: 1
time_ms: 990
memory_kb: 129276
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,n) for(int i = 0;i < n;i++)

#define int ll
#define IMAX ((1 << 31) - 1)
#define LMAX ((1LL << 63) - 1)

#define MAX_H 1001LL

vector<int> isPrime;
vector<vector<int>> caves;
map<int,pair<int,int>> mp;

void main_() {
    int n,m;
    cin >> m >> n;
    if(n == 0) exit(0);

    vector<vector<int>> dp(MAX_H, vector<int>(MAX_H, 0));

    int from_x = mp.at(n).first;
    int from_y = mp.at(n).second;

    auto primeInt = [&](int i, int j){
        if(caves[i][j] > m) return 0LL;
        return isPrime.at(caves[i][j]);
    };

    int l = from_x;
    int r = from_x + 1;
    dp[from_y][from_x] = isPrime.at(n);

    int ans = isPrime.at(n);
    int last = (isPrime.at(n) ? n : 0);
    for(int i = from_y; i < MAX_H - 1; i++){

        for(int j = l; j < r; j++){
            for(int k = -1; k <= 1; k++){
                if(j + k < 0 || j + k >= MAX_H) continue;
                dp[i+1][j + k] = max(dp[i+1][j + k], dp[i][j] + primeInt(i+1,j+k));

                if(dp[i+1][j+k] > ans){
                    ans = dp[i+1][j+k];
                    last = caves[i+1][j+k];
                } else if(dp[i + 1][j + k] == ans && primeInt(i+1,j+k)) {
                    last = max(last, caves[i+1][j+k]);
                }
            }
        }
        l = max(l-1, 0LL);
        r = min(r + 1, MAX_H);
    }

    cout << ans << " " << last << endl;
}

signed main() {
    const int MAX = MAX_H * MAX_H;
    isPrime.resize(MAX + 1, 1);
    isPrime[0] = false;
    isPrime[1] = false;
    for(int i = 2; i*i < MAX + 1; i++) {
        for(int j = i*i; j < MAX + 1; j += i) {
            isPrime.at(j) = false;
        }
    }

    caves.resize(MAX_H, vector<int>(MAX_H, 0));
    int dx[4] = {1, 0, -1, 0};
    int dy[4] = {0, -1, 0, 1};
    int dir = 3;
    int x = MAX_H / 2;
    int y = MAX_H / 2;


    for(int i = 1;i <= MAX; i++){

        caves[y][x] = i;
        mp[i] = make_pair(x,y);

        // 左確認
        {
            int left = (dir + 1) % 4;
            int nx = x + dx[left];
            int ny = y + dy[left];
            if(caves[ny][nx] == 0) dir = left;
        }

        x += dx[dir];
        y += dy[dir];
    }

//    cout << mp.at(7).first << " " << mp.at(7).second << endl;
//    cout << isPrime.at(45) << endl;

    while(1) main_();
}
accuracy: 1
time_ms: 400
memory_kb: 89328
final_rank: 15

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

bool isPrime(int x){
    if(x == 1) return false;
    for(int i = 2; i * i <= x; i++){
        if(x % i == 0) return false;
    }
    return true;
}

int main(){
    const int MAX_N = 1000;
    const int dr[4] = {1, 0, -1, 0};
    const int dc[4] = {0, 1, 0, -1};
    vector<vector<bool>> isp(MAX_N, vector<bool>(MAX_N));
    vector<vector<bool>> used(MAX_N, vector<bool>(MAX_N));
    vector<vector<int>> val(MAX_N, vector<int>(MAX_N));
    vector<pair<int, int>> idx(MAX_N * MAX_N + 10);
    {
        int r = 0, c = 0;
        int dir = 3;
        for(int i = 1000000; i >= 1; i--){
            isp[r][c] = isPrime(i);
            used[r][c] = 1;
            idx[i] = make_pair(r, c);
            val[r][c] = i;
            // if(i < 30){
            //     cout << i << " " << val[r][c] << " ";
            // }
            if(i >= 2){
                while(1){
                    int nr = r + dr[dir], nc = c + dc[dir];
                    bool flag = 1;
                    if(nr < 0 || MAX_N <= nr || nc < 0 || MAX_N <= nc) flag = 0;
                    else if(used[nr][nc]) flag = 0;
                    if(flag){
                        r = nr, c = nc;
                        break;
                    }
                    else{
                        dir = (dir + 3) % 4;
                    }
                }
            }
            // if(i < 30){
            //     cout << val[r][c] << endl;
            // }
        }
    }

    // for(int i = 495; i <= 505; i++){
    //     for(int j = 495; j <= 505; j++){
    //         cout << val[i][j] << " ";
    //     }
    //     cout << endl;
    // }

    vector<vector<pair<int, int>>> memo(MAX_N, vector<pair<int, int>>(MAX_N, make_pair(-1, -1)));
    auto rec = [&](auto f, int r, int c, int m) -> pair<int, int> {
        if(r < 0 || MAX_N <= r || c < 0 || MAX_N <= c) return make_pair(0, 0);
        if(val[r][c] > m) return make_pair(0, 0);
        if(memo[r][c].first != -1) return memo[r][c];

        int bo = 0, num = 0;
        if(isp[r][c]){
            // cout << val[r][c];
            bo = 1, num = val[r][c];
        }
        pair<int, int> mx = make_pair(0, 0);
        mx = max(mx, f(f, r + 1, c - 1, m));
        mx = max(mx, f(f, r + 1, c    , m));
        mx = max(mx, f(f, r + 1, c + 1, m));
        mx.first += bo;
        if(mx.second == 0) mx.second = num;
        return memo[r][c] = mx;
    };

    while(1){
        int M, N; cin >> M >> N;
        if(M == 0) break;
        auto [p, q] = idx[N];
        auto [a1, a2] = rec(rec, p, q, M);
        cout << a1 << " " << a2 << endl;
        for(int i = 0; i < MAX_N; i++){
            for(int j = 0; j < MAX_N; j++){
                memo[i][j] = make_pair(-1, -1);
            }
        }
    }
}
accuracy: 1
time_ms: 170
memory_kb: 23220
final_rank: 7

code_snippet: #include<bits/stdc++.h>
//#include <atcoder/all>
using namespace std;
//using namespace atcoder;

#define all(v) v.begin(),v.end()
using ll = long long;
using ull = unsigned long long;
using vll=vector<ll>;
using vvll = vector<vector<ll>>;
using P = pair<ll,ll>;
using vp=vector<pair<ll, ll>>;
//using mint=modint1000000007;
//using mint=modint998244353;

const ll INF=1ll<<60;
ll mod10=1e9+7;
ll mod99=998244353;
const double PI = acos(-1);

#define rep(i,n) for (ll i=0;i<n;++i)
#define per(i,n) for(ll i=n-1;i>=0;--i)
#define rep2(i,a,n) for (ll i=a;i<n;++i)
#define per2(i,a,n) for (ll i=a;i>=n;--i)

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }

vector<ll> dx={0,-1,0,1},dy={1,0,-1,0};
ll si=1002;
vll pri(si*si+1);
vvll A(si,vll(si,0));
ll N,M;
map<ll,P> mp;

map<P,P> mp2;

P ch(P ma,P a){
    if(ma.first<a.first) return a;
    else if(ma.first==a.first) return{ma.first,max(ma.second,a.second)};
    return ma;
}
P dfs(ll nowi,ll nowj){
    if(mp2.count({nowi,nowj})) return mp2[{nowi,nowj}];
    P ma={-1,-1};
    if(pri[A[nowi][nowj]]==A[nowi][nowj]) ma={1,A[nowi][nowj]};
    ll p=pri[A[nowi][nowj]]==A[nowi][nowj];
    if(A[nowi+1][nowj]<=M){
        auto [a,b]=dfs(nowi+1,nowj);
        ma=ch(ma,{a+p,b});
    }
    if(nowj>0&&A[nowi+1][nowj-1]<=M){
        auto [a,b]=dfs(nowi+1,nowj-1);
        ma=ch(ma,{a+p,b});
    }
    if(nowj<si-1&&A[nowi+1][nowj+1]<=M){
        auto [a,b]=dfs(nowi+1,nowj+1);
        ma=ch(ma,{a+p,b});
    }

    //cout << A[nowi][nowj]<<" "<<ma.first << endl;
    
    return mp2[{nowi,nowj}]=ma;
}



int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
 
    rep2(i,2,si*si+1){
        if(pri[i]>0) continue;
        ll j=1;
        while(i*j<=si*si) pri[i*j]=i,j++;
    }

    ll now=1;
    ll cnt=0;
    ll nowi=si/2,nowj=si/2;
    ll d=0;
    while(1){
        mp[now]={nowi,nowj};
        A[nowi][nowj]=now;
        ll toi=nowi+dx[d],toj=nowj+dy[d];
        if(!(toi<si&&toj<si)||A[toi][toj]>0){
            d=(d+3)%4;
            toi=nowi+dx[d],toj=nowj+dy[d];
            if(!(toi<si&&toj<si)||A[toi][toj]>0){
                toi=-1;
            }
        }

        if(toi==-1) break;
        now++;
        nowi=toi,nowj=toj;
        d=(d+1)%4;
    }


    while(1){
        cin>>M>>N;
        if(N==0&&M==0) break;
        mp2.clear();
        auto [a,b]=dfs(mp[N].first,mp[N].second);
        if(a==-1) a=0,b=0;
        cout<<a<<" "<<b<<endl;
    }
}
accuracy: 1
time_ms: 730
memory_kb: 128968
final_rank: 19

code_snippet: #include <bits/stdc++.h>

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);

    const int dx[4]{ 0, -1, 0, 1 };
    const int dy[4]{ 1, 0, -1, 0 };
    std::map<std::pair<int, int>, int> map;
    int x{}, y{}, d{3};
    for (int i{1} ; i <= 1000000 ; i++) {
        assert(map.find({ x, y }) == map.end());
        map[{ x, y }] = i;
        int nd{(d + 1) % 4};
        if (map.find({ x + dx[nd], y + dy[nd] }) == map.end()) {
            x += dx[nd];
            y += dy[nd];
            d = nd;
        }
        else {
            x += dx[d];
            y += dy[d];
        }
    }
    std::vector<std::pair<int, int>> rev(1000001);
    for (auto [p, i] : map) {
        rev[i] = p;
    }
    std::vector<bool> P(1000001, true);
    P[0] = P[1] = false;
    for (int i{2} ; i * i <= 1000000 ; i++) {
        if (P[i]) {
            for (int j{i + i} ; j <= 1000000 ; j += i) {
                P[j] = false;
            }
        }
    }
    while (true) {
        int n, m;
        std::cin >> m >> n;
        if (n == 0 and m == 0) break;
        std::vector<int> memo(m + 1, -1), last(m + 1);
        auto rec{[&](auto rec, int i) -> int {
            if (i > m) return -1;
            if (memo[i] != -1) return memo[i];
            memo[i] = 0;
            auto [x, y]{rev[i]};
            for (int d{-1} ; d <= 1 ; d++) {
                auto it{map.find({ x + 1, y + d })};
                if (it != map.end()) {
                    int v{rec(rec, it->second)}; 
                    if (memo[i] < v) {
                        memo[i] = v;
                        last[i] = last[it->second];
                    }
                    else if (memo[i] == v) {
                        last[i] = std::max(last[i], last[it->second]);
                    }
                }
            }
            if (P[i]) {
                memo[i]++;
                if (last[i] == 0) {
                    last[i] = i;
                }
            }
            return memo[i];
        }};
        rec(rec, n);
        // for (int i{1} ; i <= m ; i++) {
        //     std::cout << i << " -> " << memo[i] << ' ' << last[i] << std::endl;
        // }
                 
        std::cout << memo[n] << ' ' << last[n] << '\n';
    }
}
accuracy: 1
time_ms: 580
memory_kb: 81380
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define ALL(v) v.begin(),v.end()
#define dbg(x) cerr << #x << ": " << x << endl
template<class F, class S>
ostream& operator<<(ostream& os, pair<F,S> p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template<class Iter>
void print(Iter beg, Iter end) {
    for (auto itr = beg; itr != end; ++itr) {
        cerr << *itr << ' ';
    }
    cerr << '\n';
}
int MAX = 1e6;
int dx[]={1,0,-1,0};
int dy[]={0,-1,0,1};

pair<vector<vector<int>>, vector<pair<int,int>>> gen() {
    map<pair<int,int>, int> mp;
    int dir = 0;
    int len=1;
    int num = 2;
    mp[{0,0}] = 1;
    int x=0, y=0;
    int mx=0, my=0;
    while (num <= MAX) {
        for (int cnt=0; cnt < 2; ++cnt) {
            for (int i = 0; i < len; ++i) {
                x += dx[dir];
                y += dy[dir];
                mp[{x,y}] = num++;
            }
            dir = (dir + 1) % 4;
        }
        ++len;
    }
    vector<vector<int>> op(1e3+1, vector<int>(1e3+1, MAX+1));
    vector<pair<int,int>> inv(MAX+1);
    for (auto [p, id] : mp) {
        if (id > 1e6) continue;
        auto [x,y] = p;
        op[y+500][x+499] = id;
        inv[id] = {x+499, y+500};
    }
    return {op, inv};
}

int main() {
    auto [grid, inv] = gen();

    vector<bool> isPrime(MAX+1,true);
    isPrime[0] = isPrime[1] = false;
    for (int i = 2; i <= MAX; ++i) {
        if (isPrime[i]) {
            for (int j=i*2; j <= MAX; j+=i) {
                isPrime[j] = false;
            }
        }
    }

    while (true) {
        int m,n;
        cin >> m >> n;
        if (m+n == 0) break;
        map<pair<int, int>, int> dp;
        map<pair<int, int>, int> ndp;
        pair<int, int> ans;
        dp[inv[n]] = 0;
        while (!dp.empty())
        {
            for (auto &v : dp)
            {
                int x = v.first.first, y = v.first.second;
                if (isPrime[grid[y][x]])
                {
                    ++v.second;
                    ans = max(ans, make_pair(v.second, grid[y][x]));
                }
                int nx = x + 1, ny = y + 1;
                if ((0 <= nx && nx < 1e3 && 0 <= ny && ny < 1e3) && grid[ny][nx] <= m)
                {
                    auto &tmp = ndp[{nx, ny}];
                    tmp = max(tmp, v.second);
                }
                nx = x, ny = y + 1;
                if ((0 <= nx && nx < 1e3 && 0 <= ny && ny < 1e3) && grid[ny][nx] <= m)
                {
                    auto &tmp = ndp[{nx, ny}];
                    tmp = max(tmp, v.second);
                }
                nx = x - 1, ny = y + 1;
                if ((0 <= nx && nx < 1e3 && 0 <= ny && ny < 1e3) && grid[ny][nx] <= m)
                {
                    auto &tmp = ndp[{nx, ny}];
                    tmp = max(tmp, v.second);
                }
            }
            swap(dp, ndp);
            ndp.clear();
        }
        cout << ans.first << ' ' << ans.second << endl;
    }
}
accuracy: 1
time_ms: 310
memory_kb: 89036
final_rank: 14

code_snippet: // (⁠◕⁠ᴗ⁠◕⁠✿⁠)
 
#include <bits/stdc++.h>
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define srep(i, s, n) for (ll i = s; i < (n); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
template<typename T> using vc = vector<T>;
template<typename T> using vv = vc<vc<T>>;
template<typename T> using vvv = vc<vv<T>>;
using vi = vc<int>;using vvi = vv<int>; using vvvi = vv<vi>;
using ll = long long;using vl = vc<ll>;using vvl = vv<ll>; using vvvl = vv<vl>;
using ld = long double; using vld = vc<ld>; using vvld = vc<vld>; using vvvld = vc<vvld>;
using uint = unsigned int;
using ull = unsigned long long;
const double pi = 3.141592653589793;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
// const ll mod = 1000000007;
const ll mod = 998244353;
inline bool inside(long long y, long long x, long long H, long long W) {return 0 <= (y) and (y) < (H) and 0 <= (x) and (x) < (W); }


#define debug(var)  do{std::cout << #var << " : \n";view(var);}while(0)
template<typename T> void view(T e){cout << e << endl;}
template<typename T> void view(const vc<T>& v){for(const auto& e : v){ cout << e << " "; } cout << endl;}
template<typename T> void view(const vv<T>& vv){ for(const auto& v : vv){ view(v); } }

vc<bool> eratosthenes(int t){
    vc<bool> is_prime(t + 1, true);
    is_prime[0] = false; is_prime[1] = false;
    for (int i = 0; i <= t; i++){
        if (is_prime[i]){
            for (int q = i * 2; q <= t; q += i){
                is_prime[q] = false;
            }
        }
    }
    return is_prime;
}

vvi cave(2001, vi(2000, inf));
auto is_prime = eratosthenes(4004004);

vi dx = {0, -1, 0, 1}, dy = {1, 0, -1, 0};

void init(){
    int si = 1000, sj = 1000;
    cave[si][sj] = 1;
    int k = 0, num = 2;
    for (int d = 1; d <= 2000; d++){
        rep(_, 2){
            rep(t, d){
                si += dx[k];
                sj += dy[k];
                cave[si][sj] = num;
                num++;
            }
            k = (k + 1) % 4;
        }
    }
}

pair<int, int> solve(int M, int N){
    int si = 0, sj = 0;
    rep(i, 2000) rep(j, 2000) if (cave[i][j] == N){
        si = i;
        sj = j;
        break;
    }
    vvi dp(2000, vi(2000, -1));
    if (is_prime[N]) dp[si][sj] = 1;
    else dp[si][sj] = 0;
    pair<int, int> ans = {0, 0};
    if (is_prime[N]) ans = {1, N};
    rep(i, 1999) rep(j, 2000) if (dp[i][j] != -1){
        for (int nj = max(0ll, j - 1); nj <= min(1999ll, j + 1); nj++) if (cave[i + 1][nj] <= M){
            if (is_prime[cave[i + 1][nj]] && dp[i + 1][nj] < dp[i][j] + 1){
                dp[i + 1][nj] = dp[i][j] + 1;
                ans = max(ans, {dp[i + 1][nj], cave[i + 1][nj]});
            }
            if (!is_prime[cave[i + 1][nj]] && dp[i + 1][nj] < dp[i][j]){
                dp[i + 1][nj] = dp[i][j];
            }
        }
    }
    return ans;
}

int main(){
    vc<pair<int, int>> ans;
    init();
    while (true){
        int M, N; cin >> M >> N;
        if (M == 0) break;
        ans.push_back(solve(M, N));
    }
    for (auto x : ans) cout << x.first << " " << x.second << endl;
}
accuracy: 1
time_ms: 430
memory_kb: 35132
final_rank: 12

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

pair<int, int> Solve(int N, int M, vector<bool> primes) {
	vector<vector<int>> Grid(1200, vector<int>(1200, 0));

	// Get Grid
	int sx = 600, ax = -1;
	int sy = 600, ay = -1;
	int cnt = 1;
	const int dx[4] = {0, -1, 0, 1};
	const int dy[4] = {1, 0, -1, 0};
	Grid[600][600] = 1;
	if (M == 1) { ax = 600; ay = 600; }

	// Grid Main
	for (int r = 2; r < 5000; r++) {
		for (int i = 0; i < r / 2; i++) {
			sx += dx[(r + 2) % 4];
			sy += dy[(r + 2) % 4];
			cnt += 1;
			Grid[sx][sy] = cnt;
			if (cnt == M) { ax = sx; ay = sy; }
			if (cnt == N) break;
		}
		if (cnt == N) break;
	}

	// Dynamic Programming
	vector<vector<pair<int, int>>> dp(1200, vector<pair<int, int>>(1200, make_pair(-1000000, -1)));
	for (int i = 1; i <= 1198; i++) {
		for (int j = 1; j <= 1198; j++) {
			if (Grid[i][j] == M) {
				dp[i][j] = make_pair(0, 0);
				if (primes[M] == true) dp[i][j] = make_pair(1, M);
			}
			else {
				dp[i][j] = max({dp[i - 1][j - 1], dp[i - 1][j], dp[i - 1][j + 1]});
				if (primes[Grid[i][j]] == true) {
					dp[i][j].first += 1;
					dp[i][j].second = Grid[i][j];
				}
			}
		}
	}

	// Return
	pair<int, int> Answer = make_pair(0, 0);
	for (int i = 1; i <= 1198; i++) Answer = max(Answer, dp[1198][i]);
	return Answer;
}

int main() {
	vector<bool> primes(1000001, true);
	primes[0] = false;
	primes[1] = false;
	for (int i = 2; i <= 1000000; i++) {
		for (int j = 2 * i; j <= 1000000; j += i) primes[j] = false;
	}

	// Simulation
	while (true) {
		int N, M; cin >> N >> M;
		if (N == 0 && M == 0) break;
		pair<int, int> ret = Solve(N, M, primes);
		cout << ret.first << " " << ret.second << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 20260
final_rank: 9

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

pair<int, int> Solve(int N, int M, vector<bool> primes) {
	vector<vector<int>> Grid(1200, vector<int>(1200, 0));
	int sx = 600, ax = -1;
	int sy = 600, ay = -1;
	int cnt = 1;
	const int dx[4] = {0, -1, 0, 1};
	const int dy[4] = {1, 0, -1, 0};
	Grid[600][600] = 1;
	if (M == 1) { ax = 600; ay = 600; }

	// Get Grid
	for (int r = 0; r <= 6000; r++) {
		for (int i = 0; i < (r + 2) / 2; i++) {
			sx += dx[r % 4];
			sy += dy[r % 4];
			cnt += 1;
			Grid[sx][sy] = cnt;
			if (cnt == M) { ax = sx; ay = sy; }
			if (cnt == N) break;
		}
		if (cnt == N) break;
	}

	// Dynamic Programming
	vector<vector<pair<int, int>>> dp(1200, vector<pair<int, int>>(1200, make_pair(-1000000, -1)));
	for (int i = 1; i <= 1198; i++) {
		for (int j = 1; j <= 1198; j++) {
			if (i == ax && j == ay) {
				dp[i][j] = make_pair(0, 0);
				if (primes[M] == true) dp[i][j] = make_pair(1, M);
			}
			else {
				dp[i][j] = max({dp[i - 1][j - 1], dp[i - 1][j], dp[i - 1][j + 1]});
				if (primes[Grid[i][j]] == true) {
					dp[i][j].first += 1;
					dp[i][j].second = Grid[i][j];
				}
			}
		}
	}

	// Get Answer
	pair<int, int> Answer = make_pair(0, 0);
	for (int i = 1; i <= 1198; i++) Answer = max(Answer, dp[1198][i]);
	return Answer;
}

int main() {
	vector<bool> primes(1000001, true);
	primes[0] = false;
	primes[1] = false;
	for (int i = 2; i <= 1000000; i++) {
		for (int j = i * 2; j <= 1000000; j += i) primes[j] = false;
	}

	// Simulation
	while (true) {
		int N, M; cin >> N >> M;
		if (N == 0 && M == 0) break;
		pair<int, int> ret = Solve(N, M, primes);
		cout << ret.first << " " << ret.second << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 480
memory_kb: 20264
final_rank: 10

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

const int dx[4] = {0, -1, 0, 1};
const int dy[4] = {1, 0, -1, 0};

pair<int, int> Solve(int N, int M, vector<bool> primes) {
	vector<vector<int>> Grid(1200, vector<int>(1200, 0));
	int px = 600, sx = -1;
	int py = 600, sy = -1;
	int dir = 0;
	int cnt = 1;
	Grid[600][600] = 1;

	// Get Index
	for (int loop = 1; loop <= 6000; loop++) {
		for (int i = 0; i < (loop + 1) / 2; i++) {
			px += dx[dir];
			py += dy[dir];
			cnt += 1;
			Grid[px][py] = cnt;
			if (cnt == N) break;
		}
		dir = (dir + 1) % 4;
		if (cnt == N) break;
	}
	for (int i = 1; i <= 1198; i++) {
		for (int j = 1; j <= 1198; j++) {
			if (Grid[i][j] == M) { sx = i; sy = j; }
		}
	}

	// DP Main
	vector<vector<pair<int, int>>> dp(1200, vector<pair<int, int>>(1200, make_pair(-100000000, -1)));
	for (int i = 1; i <= 1198; i++) {
		for (int j = 1; j <= 1198; j++) {
			if (i == sx && j == sy) {
				if (primes[M] == true) dp[i][j] = make_pair(1, M);
				else dp[i][j] = make_pair(0, 0);
			}
			else {
				dp[i][j] = max({dp[i - 1][j - 1], dp[i - 1][j], dp[i - 1][j + 1]});
				if (primes[Grid[i][j]] == true) {
					dp[i][j].first += 1;
					dp[i][j].second = Grid[i][j];
				}
			}
		}
	}

	// Return
	pair<int, int> Answer = make_pair(0, 0);
	for (int i = 1; i <= 1198; i++) Answer = max(Answer, dp[1198][i]);
	return Answer;
}

int main() {
	// Step 1. Enumerate Primes
	vector<bool> primes(1000001, true);
	primes[0] = false;
	primes[1] = false;
	for (int i = 2; i <= 1000000; i++) {
		for (int j = i * 2; j <= 1000000; j += i) primes[j] = false;
	}

	// Step 2. Simulation
	while (true) {
		int N, M; cin >> N >> M; if (N == 0 && M == 0) break;
		pair<int, int> ret = Solve(N, M, primes);
		cout << ret.first << " " << ret.second << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 490
memory_kb: 20324
final_rank: 11