#include <iostream>
#include <vector>
using namespace std;
// 최대 입력이 백만, 백만을 넘는 최소 소수는 백만삼
#define MAX_INPUT 1000005
// 전체를 검사하지 않기 위해 입력된 수에서 +ADD_NUM 까지만 검사하도록 한다.
#define ADD_NUM 200
// 소수와 합성수를 표현
enum { PRIME = 0, COMPOSIT = 1 };
void Initialize(int arr[], int N, vector<int>& prime);
void Eratos(vector<int>& prime, int max);
void PrintResult(int *arr, int N, vector<int>& prime);
int PrimeCheckArr[MAX_INPUT];
int main(void)
{
vector<int> prime;
int *arr;
int N;
cin >> N;
arr = new int[N];
Initialize(arr, N, prime);
PrintResult(arr, N, prime);
delete[] arr;
}
// 배열 값 초기화 함수
void Initialize(int arr[], int N, vector<int>& prime)
{
int max = 0;
for (int i = 0; i < N; ++i)
{
cin >> arr[i];
// 입력 받는 수 중 최대값을 찾는다.
if (arr[i] > max) max = arr[i];
}
// 소수를 구분하기 위한 배열을 초기화 해준다.
for (int i = 0; i < max+ ADD_NUM; ++i)
PrimeCheckArr[i] = i + 1;
Eratos(prime, max);
}
void Eratos(vector<int>& prime, int max)
{
// MAX_INPUT 만큼을 다 돌지 않고 작은 수가 들어온 경우 작은 범위만 돌도록 한다.
for (int i = 1; i < max+ ADD_NUM; ++i)
{
if (PrimeCheckArr[i] == COMPOSIT) continue;
// 소수인 경우 소수를 저장할 배열에 저장
prime.emplace_back(PrimeCheckArr[i]);
if (PrimeCheckArr[i] > max) break;
// 이 소수의 배수들은 합성수이므로 제외
for (int j = i + PrimeCheckArr[i]; j < max+ ADD_NUM; j += PrimeCheckArr[i])
{
PrimeCheckArr[j] = COMPOSIT;
}
}
}
void PrintResult(int *arr, int N, vector<int>& prime)
{
int leftDiff, rightDiff;
for (int i = 0; i < N; ++i)
{
int j;
for (j = 0; j < prime.size(); ++j)
{
// 소수가 기준 값보다 크거나 같은 경우
// 가장 차이가 작은것은 그 소수이거나 바로 직전의 소수 두가지 경우
if (prime[j] >= arr[i]) { break; }
}
// 기준 값 가까이에 있는 두 소수가 각각 얼마 차이나는지 저장
leftDiff = arr[i] - prime[j-1];
rightDiff = prime[j] - arr[i];
// 차이값이 동일하면 작은 소수부터 출력
if (leftDiff == rightDiff)
{
cout << prime[j - 1] << ' ' << prime[j] << endl;
}
// 그 외의 경우엔 차이값이 작은 소수를 출력
else if (leftDiff < rightDiff)
{
cout << prime[j - 1] << endl;
}
else
{
cout << prime[j] << endl;
}
}
}