#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <utility>
#include <queue>
#include <tuple>

#define REP(i, a, b) for (int i = int(a); i < int(b); i++)
#define dump(val) cerr << __LINE__ << ":\t" << #val << " = " << (val) << endl

using namespace std;

typedef long long int lli;
typedef pair<int, int> pii;

template<typename T>
vector<T> make_v(size_t a, T b) {
    return vector<T>(a, b);
}

template<typename... Ts>
auto make_v(size_t a, Ts... ts) {
    return vector<decltype(make_v(ts...))>(a, make_v(ts...));
}

int main() {
    int m, n;
    int sz = 1000010;
    vector<bool> isPrime(sz, true);
    isPrime[0] = isPrime[1] = false;
    REP(i, 0, sz) {
        if (isPrime[i]) {
            for (int j = 2 * i; j < sz; j += i) {
                isPrime[j] = false;
            }
        }
    }

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

    while (cin >> m >> n, m + n) {
        vector<vector<pii>> mp(bs * 2 + 1, vector<pii>(bs * 2 + 1));
        vector<vector<int>> prevP(bs * 2 + 1, vector<int>(bs * 2 + 1));
        int sx, sy;
        {
            int y = 0, x = 0, z = 0, k = 3;
            REP(i, 1, m + 1) {
                if (i == n) {
                    sx = x;
                    sy = y;
                }
                mp[y + bs][x + bs] = {i, isPrime[i]};
                prevP[y + bs][x + bs] = (isPrime[i] ? i : 0);
                if (i == (2 * z + 1) * (2 * z + 1)) {
                    z++;
                }
                if (abs(x + dx[k]) > z || abs(y + dy[k]) > z) {
                    k = (k + 1) % 4;
                }
                x += dx[k];
                y += dy[k];
            }
        }
        int num = prevP[sy + bs][sx + bs], ans = isPrime[n];
        vector<vector<bool>> used(bs * 2 + 1, vector<bool>(bs * 2 + 1, false));
        queue<pii> q;
        q.push({sy, sx});
        while (q.size()) {
            int x, y;
            tie(y, x) = q.front();
            q.pop();
            if (used[y + bs][x + bs]) continue;
            used[y + bs][bs + x] = true;
            REP(k, 1, 4) {
                int nx = x + dx[k], ny = y + 1;
                if (mp[ny + bs][nx + bs].first == 0) continue;
                auto &ne = mp[ny + bs][nx + bs];
                auto &pe = mp[y + bs][x + bs];

                if (ne.second < pe.second + isPrime[ne.first]) {
                    ne.second = pe.second + isPrime[ne.first];
                    if (!isPrime[ne.first]) {
                        prevP[ny + bs][nx + bs] = prevP[y + bs][x + bs];
                    }
                } else if (ne.second == pe.second + isPrime[ne.first]) {
                    if (!isPrime[ne.first]) {
                        prevP[ny + bs][nx + bs] = max(prevP[ny + bs][nx + bs], prevP[y + bs][x + bs]);
                    }
                }
                /*
                mp[ny + bs][nx + bs].second = max(mp[ny + bs][nx + bs].second, mp[y + bs][x + bs].second + isPrime[mp[ny + bs][nx + bs].first]);
                if (!isPrime[mp[ny + bs][nx + bs].first]) {
                    prevP[ny + bs][nx + bs] = max(prevP[ny + bs][nx + bs], prevP[y + bs][x + bs]);
                }
                */
                q.emplace(ny, nx);
                if (ans < mp[ny + bs][nx + bs].second) {
                    ans = mp[ny + bs][nx + bs].second;
                    num = prevP[ny + bs][nx + bs];
                } else if (ans == mp[ny + bs][nx + bs].second && num < prevP[ny + bs][nx + bs]) {
                    num = prevP[ny + bs][nx + bs];
                }
            }
        }
        cout << ans << " " << num << endl;
    }
    return 0;
}



Measured memory_bytes: 15596