#include <stdio.h>
#define A 1000000
#define B 2020
#include<math.h>

int m,s;
typedef struct{
    int count; //ここを調査した後の，調査してきた洞窟の総数の最大値
    int num; //0からスタート，何番目の洞窟か
    int last;
} cave_struct;
cave_struct cave[B][B]; //cave[1000][1000]が0番目に対応

int N[A] = {}; //0が格納されていれば（添字＋1）は素数．全て素数で初期化．
void setPrime(){
    int i, j;
    int sqrt_A = sqrt(A);
    N[0] = 1;
    for(i = 1; i <= sqrt_A; i++){
        if(N[i] == 0){
            for(j = 2; j * (i + 1) <= A; j++){
                N[j * (i + 1) - 1] = 1;
            }
        }
    }
}
int co = 0;
int pos_x = 1000, pos_y = 1000, f_x, f_y;
int next = 1;
void setCave_1(){
    int i,j;
    for(i = 0; i < B; i++){
        for(j = 0; j < B; j++){
            cave[i][j].count = -1;
            cave[i][j].num = -1; //未登録
        }
    }
}
void setCave(){
    int i;
    while(1){
        for(i = 0; i < next; i++){
            //右へ
            cave[pos_y][pos_x++].num = co++;
            if(co == s){
                f_x = pos_x-1; f_y = pos_y;
            }
            if(co > m-1) break;
        }
        if(co > m-1) break;
        for(i = 0; i < next; i++){
            //上へ
            cave[pos_y--][pos_x].num = co++;
            if(co == s){
                f_x = pos_x; f_y = pos_y+1;
            }
            if(co > m-1) break;
        }
        if(co > m-1) break;
        next++;
        for(i = 0; i < next; i++){
            //左へ
            cave[pos_y][pos_x--].num = co++;
            if(co == s){
                f_x = pos_x+1; f_y = pos_y;
            }
            if(co > m-1) break;
        }
        if(co > m-1) break;
        for(i = 0; i < next; i++){
            //下へ
            cave[pos_y++][pos_x].num = co++;
            if(co == s){
                f_x = pos_x; f_y = pos_y-1;
            }
            if(co > m-1) break;
        }
        if(co > m-1) break;
        next++;
    }
    cave[f_y][f_x].count = 1 - N[cave[f_y][f_x].num];
    //printf("%d\n",cave[f_y][f_x].count);
    if(cave[f_y][f_x].num == 1){
                cave[f_y][f_x].last = cave[f_y][f_x].num;
     }

}

int max_last = 0;
int max = -1;
void expCave(int y, int x){
    if(cave[y][x].count == -1) return;
    //printf("%d, %d\n",cave[y][x].num+1,cave[y][x].count);
    //printf(" %d, %d\n",max_last,max);


    if(cave[y][x].count > max){
        max = cave[y][x].count;
        max_last = cave[y][x].last;
        //printf("%d, %d\n",cave[y][x].num+1,cave[y][x].count);
        //printf("  %d, %d\n",max_last,max);
    }else if(cave[y][x].count == max && cave[y][x].last > max_last){
        max = cave[y][x].count;
        max_last = cave[y][x].last;
        //printf("  %d, %d\n",max_last,max);
    }


    //printf(" %d, %d\n",max_last,max);
    if(cave[y+1][x-1].num != -1){
        if(cave[y+1][x-1].count <= cave[y][x].count){
            cave[y+1][x-1].count = cave[y][x].count;
            if(N[cave[y+1][x-1].num] == 0){
                cave[y+1][x-1].last = cave[y+1][x-1].num;
                cave[y+1][x-1].count++;
                if(cave[y+1][x-1].count > max){
                    max = cave[y+1][x-1].count;
                    max_last = cave[y+1][x-1].last;
                    //printf("%d, %d\n",max_last,max);
                }else if(cave[y+1][x-1].count == max && cave[y+1][x-1].num > max_last){
                    max = cave[y+1][x-1].count;
                    max_last = cave[y+1][x-1].num;
                    //printf("%d, %d\n",max_last,max);
                }
            }else{
                cave[y+1][x-1].last = cave[y][x].last;
            }
        }
    }
    //printf(" %d, %d\n",max_last,max);
    if(cave[y+1][x].num != -1){
        if(cave[y+1][x].count <= cave[y][x].count){
            cave[y+1][x].count = cave[y][x].count;
            if(N[cave[y+1][x].num] == 0){
                cave[y+1][x].last = cave[y+1][x-1].num;
                cave[y+1][x].count++;
                if(cave[y+1][x].count > max){
                    max = cave[y+1][x].count;
                    max_last = cave[y+1][x].last;
                    //printf("%d, %d\n",max_last,max);
                }else if(cave[y+1][x].count == max && cave[y+1][x].num > max_last){
                    max = cave[y+1][x].count;
                    max_last = cave[y+1][x].num;
                    //printf("%d, %d\n",max_last,max);
                }
            }else{
                cave[y+1][x].last = cave[y][x].last;
            }
        }
    }
    //printf(" %d, %d\n",max_last,max);
    if(cave[y+1][x+1].num != -1){
        if(cave[y+1][x+1].count <= cave[y][x].count){
            cave[y+1][x+1].count = cave[y][x].count;
            if(N[cave[y+1][x+1].num] == 0){
                cave[y+1][x+1].last = cave[y+1][x-1].num;
                cave[y+1][x+1].count++;
                if(cave[y+1][x+1].count > max){
                    max = cave[y+1][x+1].count;
                    max_last = cave[y+1][x+1].last;
                    //printf("%d, %d\n",max_last,max);
                }else if(cave[y+1][x+1].count == max && cave[y+1][x+1].num > max_last){
                    max = cave[y+1][x+1].count;
                    max_last = cave[y+1][x+1].num;
                    //printf("%d, %d\n",max_last,max);
                }
            }else{
                cave[y+1][x+1].last = cave[y][x].last;
            }
        }
    }
    //printf(" %d, %d\n",max_last,max);

}

int main(void){
    setPrime();
    //while(1){
        scanf("%d %d", &m, &s);
        //if(!m && !s) break;
        co = 0; pos_x = 1000; pos_y = 1000; next = 1; max_last = 0; max = -1;
        setCave_1();
        setCave();
        //printf("(%d, %d)\n",f_x,f_y);
        for(int i = 1; i < B-1; i++){
            for(int j = 1; j < B-1; j++){
                expCave(i, j);
            }
        }
        printf("%d %d\n",max,max_last+1);
        
        for(int i =  997; i <= 1003; i++){
            for(int j = 997; j <= 1003; j++){
                printf("%2d ",cave[i][j].num);
            }
            printf("\n");
        }
        
    //}
    return 0;
}
