You have an array a[1], a[2], ..., a[n], containing distinct integers from 1 to n. Your task is to sort this array in increasing order with the following operation (you may need to apply it multiple times):

  choose two indexes, i and j (1 ≤ i < j ≤ n; (j - i + 1) is a prime number);  swap the elements on positions i and j; in other words, you are allowed to apply the following sequence of assignments: tmp = a[i], a[i] = a[j], a[j] = tmp (tmp is a temporary variable). 

You do not need to minimize the number of used operations. However, you need to make sure that there are at most 5n operations.


-----Input-----

The first line contains integer n (1 ≤ n ≤ 10^5). The next line contains n distinct integers a[1], a[2], ..., a[n] (1 ≤ a[i] ≤ n).


-----Output-----

In the first line, print integer k (0 ≤ k ≤ 5n) — the number of used operations. Next, print the operations. Each operation must be printed as "i j" (1 ≤ i < j ≤ n; (j - i + 1) is a prime).

If there are multiple answers, you can print any of them.


-----Examples-----
Input
3
3 2 1

Output
1
1 3

Input
2
1 2

Output
0

Input
4
4 2 3 1

Output
3
2 4
1 2
2 4

Difficulty: MEDIUM_HARD
Tags: Sorting

Greedy algorithms
Skill types: Sorting

Greedy algorithms

Starter code:

Solutions:
import bisect

def gen_primes(upper_bound):
	upper_bound += 1
	t = [0] * upper_bound
	primes = [2]
	for i in range(3, upper_bound, 2):
		if t[i]:
			continue
		primes.append(i)
		for j in range(i + i, upper_bound, i):
			t[j] = 1
	return primes

def main():
	n = int(input())
	a = list(map(int, input().split()))
	primes = gen_primes(n + 1)
	process = list()
	d = [0] * n
	for i in range(n):
		d[a[i] - 1] = i
	i = 0
	while i < n:
		if a[i] == i + 1:
			i += 1
			continue
		r = d[i]
		l = r - primes[bisect.bisect(primes, r - i + 1) - 1] + 1
		(a[l], a[r]) = (a[r], a[l])
		process.append('{} {}'.format(l + 1, r + 1))
		d[a[l] - 1] = l
		d[a[r] - 1] = r
	print(len(process))
	print('\n'.join(process))

def __starting_point():
	main()
__starting_point()


N = int(200000.0 + 3)
primes = []
is_prime = [1] * N
is_prime[0] = is_prime[1] = 0
for i in range(2, N):
	if is_prime[i] == 0:
		continue
	primes.append(i)
	for j in range(i + i, N, i):
		is_prime[j] = 0
n = int(input())
arr = list(map(int, input().split()))
prt = [0] * n
for i in range(n):
	arr[i] -= 1
	prt[arr[i]] = i

def binary_search(k):
	(b, e) = (0, len(primes))
	while b <= e:
		mid = b + e >> 1
		if primes[mid] <= k:
			b = mid + 1
		else:
			e = mid - 1
	return b
res = []
p = 0
while p < n:
	while prt[p] != p:
		d = prt[p] - p + 1
		d = primes[binary_search(d) - 1] - 1
		r = prt[p]
		q = r - d
		(prt[arr[q]], prt[arr[r]]) = (prt[arr[r]], prt[arr[q]])
		(arr[q], arr[r]) = (arr[r], arr[q])
		res.append(str(q + 1) + ' ' + str(r + 1))
	p += 1
print(len(res))
print('\n'.join(res))


def sieve(n):
	p = 2
	while p * p <= n:
		if prime[p] == False:
			for i in range(p * p, n + 1, p):
				prime[i] = True
		p += 1
n = int(input())
prime = [False for i in range(n + 2)]
prime[0] = 1
prime[1] = 1
sieve(n + 1)
lis = [0] + list(map(int, input().split()))
ind = [0] * (n + 1)
ct = 0
for i in range(1, n + 1):
	ind[lis[i]] = i
ans = []
for i in range(1, n + 1):
	j = ind[i]
	while j > i:
		t = i
		while prime[j - t + 1]:
			t += 1
		ct += 1
		ind[lis[j]] = t
		ind[lis[t]] = j
		ans.append([t, j])
		(lis[j], lis[t]) = (lis[t], lis[j])
		j = t
print(ct)
for i in ans:
	print(*i)


def sieve(n):
	prime = [-1] * (n + 1)
	for i in range(2, n + 1):
		if prime[i] == -1:
			for j in range(i, n + 1, i):
				prime[j] = i
	return prime
p = sieve(100010)
prime = []
for i in range(len(p)):
	if p[i] == i:
		prime.append(p[i])

def find_prime(num):
	low = 0
	high = len(prime) - 1
	while low < high:
		mid = (low + high) // 2
		if prime[mid] < num:
			low = mid + 1
		else:
			high = mid - 1
	if prime[low] <= num:
		return prime[low]
	else:
		return prime[low - 1]

def calc(ind):
	ans = []
	num = loc[arr[ind][0]]
	while num - ind > 0:
		p = find_prime(num - ind + 1)
		(loc[a[num - p + 1]], loc[a[num]]) = (loc[a[num]], loc[a[num - p + 1]])
		(a[num], a[num - p + 1]) = (a[num - p + 1], a[num])
		ans.append([num - p + 2, num + 1])
		num -= p - 1
	return ans
n = int(input())
a = list(map(int, input().split()))
loc = {}
for i in range(n):
	loc[a[i]] = i
arr = []
for i in range(n):
	arr.append([a[i], i])
arr.sort()
i = 0
ans = []
while i < n:
	if arr[i][0] == a[i]:
		i += 1
		continue
	ans.extend(calc(i))
	i += 1
print(len(ans))
for i in ans:
	print(*i)


import sys
from math import gcd, sqrt, ceil, log2
from collections import defaultdict, Counter, deque
from bisect import bisect_left, bisect_right
import math
sys.setrecursionlimit(2 * 10 ** 5 + 10)
import heapq
from itertools import permutations
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192
aa = 'abcdefghijklmnopqrstuvwxyz'

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def get_sum(bit, i):
	s = 0
	i += 1
	while i > 0:
		s += bit[i]
		i -= i & -i
	return s

def update(bit, n, i, v):
	i += 1
	while i <= n:
		bit[i] += v
		i += i & -i

def modInverse(b, m):
	g = math.gcd(b, m)
	if g != 1:
		return -1
	else:
		return pow(b, m - 2, m)

def primeFactors(n):
	sa = []
	while n % 2 == 0:
		sa.append(2)
		n = n // 2
	for i in range(3, int(math.sqrt(n)) + 1, 2):
		while n % i == 0:
			sa.append(i)
			n = n // i
	if n > 2:
		sa.append(n)
	return sa

def seive(n):
	pri = [True] * (n + 1)
	p = 2
	while p * p <= n:
		if pri[p] == True:
			for i in range(p * p, n + 1, p):
				pri[i] = False
		p += 1
	return pri

def check_prim(n):
	if n < 0:
		return False
	for i in range(2, int(sqrt(n)) + 1):
		if n % i == 0:
			return False
	return True

def getZarr(string, z):
	n = len(string)
	(l, r, k) = (0, 0, 0)
	for i in range(1, n):
		if i > r:
			(l, r) = (i, i)
			while r < n and string[r - l] == string[r]:
				r += 1
			z[i] = r - l
			r -= 1
		else:
			k = i - l
			if z[k] < r - i + 1:
				z[i] = z[k]
			else:
				l = i
				while r < n and string[r - l] == string[r]:
					r += 1
				z[i] = r - l
				r -= 1

def search(text, pattern):
	concat = pattern + '$' + text
	l = len(concat)
	z = [0] * l
	getZarr(concat, z)
	ha = []
	for i in range(l):
		if z[i] == len(pattern):
			ha.append(i - len(pattern) - 1)
	return ha

def mergeIntervals(arr):
	arr.sort(key=lambda x: x[0])
	m = []
	s = -10000
	max = -100000
	for i in range(len(arr)):
		a = arr[i]
		if a[0] > max:
			if i != 0:
				m.append([s, max])
			max = a[1]
			s = a[0]
		elif a[1] >= max:
			max = a[1]
	if max != -100000 and [s, max] not in m:
		m.append([s, max])
	return m

class SortedList:

	def __init__(self, iterable=[], _load=200):
		values = sorted(iterable)
		self._len = _len = len(values)
		self._load = _load
		self._lists = _lists = [values[i:i + _load] for i in range(0, _len, _load)]
		self._list_lens = [len(_list) for _list in _lists]
		self._mins = [_list[0] for _list in _lists]
		self._fen_tree = []
		self._rebuild = True

	def _fen_build(self):
		self._fen_tree[:] = self._list_lens
		_fen_tree = self._fen_tree
		for i in range(len(_fen_tree)):
			if i | i + 1 < len(_fen_tree):
				_fen_tree[i | i + 1] += _fen_tree[i]
		self._rebuild = False

	def _fen_update(self, index, value):
		if not self._rebuild:
			_fen_tree = self._fen_tree
			while index < len(_fen_tree):
				_fen_tree[index] += value
				index |= index + 1

	def _fen_query(self, end):
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		x = 0
		while end:
			x += _fen_tree[end - 1]
			end &= end - 1
		return x

	def _fen_findkth(self, k):
		_list_lens = self._list_lens
		if k < _list_lens[0]:
			return (0, k)
		if k >= self._len - _list_lens[-1]:
			return (len(_list_lens) - 1, k + _list_lens[-1] - self._len)
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		idx = -1
		for d in reversed(range(len(_fen_tree).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(_fen_tree) and k >= _fen_tree[right_idx]:
				idx = right_idx
				k -= _fen_tree[idx]
		return (idx + 1, k)

	def _delete(self, pos, idx):
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len -= 1
		self._fen_update(pos, -1)
		del _lists[pos][idx]
		_list_lens[pos] -= 1
		if _list_lens[pos]:
			_mins[pos] = _lists[pos][0]
		else:
			del _lists[pos]
			del _list_lens[pos]
			del _mins[pos]
			self._rebuild = True

	def _loc_left(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(lo, pos) = (-1, len(_lists) - 1)
		while lo + 1 < pos:
			mi = lo + pos >> 1
			if value <= _mins[mi]:
				pos = mi
			else:
				lo = mi
		if pos and value <= _lists[pos - 1][-1]:
			pos -= 1
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value <= _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def _loc_right(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(pos, hi) = (0, len(_lists))
		while pos + 1 < hi:
			mi = pos + hi >> 1
			if value < _mins[mi]:
				hi = mi
			else:
				pos = mi
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value < _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def add(self, value):
		_load = self._load
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len += 1
		if _lists:
			(pos, idx) = self._loc_right(value)
			self._fen_update(pos, 1)
			_list = _lists[pos]
			_list.insert(idx, value)
			_list_lens[pos] += 1
			_mins[pos] = _list[0]
			if _load + _load < len(_list):
				_lists.insert(pos + 1, _list[_load:])
				_list_lens.insert(pos + 1, len(_list) - _load)
				_mins.insert(pos + 1, _list[_load])
				_list_lens[pos] = _load
				del _list[_load:]
				self._rebuild = True
		else:
			_lists.append([value])
			_mins.append(value)
			_list_lens.append(1)
			self._rebuild = True

	def discard(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_right(value)
			if idx and _lists[pos][idx - 1] == value:
				self._delete(pos, idx - 1)

	def remove(self, value):
		_len = self._len
		self.discard(value)
		if _len == self._len:
			raise ValueError('{0!r} not in list'.format(value))

	def pop(self, index=-1):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		value = self._lists[pos][idx]
		self._delete(pos, idx)
		return value

	def bisect_left(self, value):
		(pos, idx) = self._loc_left(value)
		return self._fen_query(pos) + idx

	def bisect_right(self, value):
		(pos, idx) = self._loc_right(value)
		return self._fen_query(pos) + idx

	def count(self, value):
		return self.bisect_right(value) - self.bisect_left(value)

	def __len__(self):
		return self._len

	def __getitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		return self._lists[pos][idx]

	def __delitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		self._delete(pos, idx)

	def __contains__(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_left(value)
			return idx < len(_lists[pos]) and _lists[pos][idx] == value
		return False

	def __iter__(self):
		return (value for _list in self._lists for value in _list)

	def __reversed__(self):
		return (value for _list in reversed(self._lists) for value in reversed(_list))

	def __repr__(self):
		return 'SortedList({0})'.format(list(self))

def ncr(n, r, p):
	num = den = 1
	for i in range(r):
		num = num * (n - i) % p
		den = den * (i + 1) % p
	return num * pow(den, p - 2, p) % p

def sol(n):
	seti = set()
	for i in range(1, int(sqrt(n)) + 1):
		if n % i == 0:
			seti.add(n // i)
			seti.add(i)
	return seti

def lcm(a, b):
	return a * b // gcd(a, b)

def moore_voting(l):
	count1 = 0
	count2 = 0
	first = 10 ** 18
	second = 10 ** 18
	n = len(l)
	for i in range(n):
		if l[i] == first:
			count1 += 1
		elif l[i] == second:
			count2 += 1
		elif count1 == 0:
			count1 += 1
			first = l[i]
		elif count2 == 0:
			count2 += 1
			second = l[i]
		else:
			count1 -= 1
			count2 -= 1
	for i in range(n):
		if l[i] == first:
			count1 += 1
		elif l[i] == second:
			count2 += 1
	if count1 > n // 3:
		return first
	if count2 > n // 3:
		return second
	return -1
pr = set()
yo = []
for i in range(1, 10 ** 5 + 45):
	if check_prim(i):
		pr.add(i)
		yo.append(i)
n = int(input())
l = list(map(int, input().split()))
hash = defaultdict(int)
for i in range(n):
	hash[l[i]] = i
j = 0
ans = []
for i in range(n):
	z = hash[j + 1]
	if z == j:
		j += 1
		continue
	while l[i] != i + 1:
		z = hash[j + 1]
		lo = bisect_right(yo, z - j + 1)
		lo = yo[lo - 1]
		(hash[l[z]], hash[l[z - lo + 1]]) = (hash[l[z - lo + 1]], hash[l[z]])
		(l[z], l[z - lo + 1]) = (l[z - lo + 1], l[z])
		ans.append([z - lo + 2, z + 1])
	j += 1
print(len(ans))
for (a, b) in ans:
	(a, b) = (min(a, b), max(a, b))
	print(a, b)


import sys
input = sys.stdin.readline
I = lambda : list(map(int, input().split()))
(n,) = I()
l = I()
an = []
sv = [0] * (10 ** 5 + 10)
for i in range(2, len(sv)):
	if not sv[i]:
		sv[i] = i
		for j in range(2 * i, len(sv), i):
			sv[j] = 1
sv[0] = sv[1] = 1
for i in range(2, len(sv)):
	if not sv[i] - 1:
		sv[i] = sv[i - 1]
ix = [0] * (n + 1)
for i in range(n):
	ix[l[i]] = i
for i in range(n):
	ct = 0
	while l[i] != i + 1 and ct < 5:
		cr = ix[i + 1]
		pr = sv[cr - i + 1]
		an.append(sorted([cr + 1, cr - pr + 2]))
		(l[cr], l[cr - pr + 1]) = (l[cr - pr + 1], l[cr])
		(ix[l[cr]], ix[l[cr - pr + 1]]) = (ix[l[cr - pr + 1]], ix[l[cr]])
		ct += 1
print(len(an))
for i in an:
	print(*i)


from sys import stdin, stdout
nmbr = lambda : int(stdin.readline())
lst = lambda : list(map(int, stdin.readline().split()))
N = 10 ** 5 + 5
primes = [1] * N
p = 2
while p * p <= N:
	if primes[p]:
		for j in range(p * p, N, p):
			primes[j] = 0
	p += 1
primes[0] = primes[1] = 0
for i in range(2, N):
	if primes[i] == 0:
		primes[i] = primes[i - 1]
	else:
		primes[i] = i
for _ in range(1):
	n = nmbr()
	a = lst()
	ind = [0] * (1 + n)
	for i in range(1, 1 + n):
		ind[a[i - 1]] = i
	p = 1
	ans = []
	while p <= n:
		pos = ind[p]
		while pos > p:
			near = primes[pos - p + 1]
			ans += [[pos - near + 1, pos]]
			(ind[a[pos - 1]], ind[a[pos - near + 1 - 1]]) = (ind[a[pos - near + 1 - 1]], ind[a[pos - 1]])
			(a[pos - 1], a[pos - near + 1 - 1]) = (a[pos - near + 1 - 1], a[pos - 1])
			pos = pos - near + 1
		p += 1
	print(len(ans))
	for (k, v) in ans:
		print(k, v)


from bisect import *
from sys import stdin
f = stdin
n = int(f.readline())
primes = [1] * (n + 1)
primes[0] = 0
primes[1] = 0
for i in range(2, n + 1):
	if primes[i] != 0:
		for j in range(i + i, n + 1, i):
			primes[j] = 0
primes = [i - 1 for i in range(n + 1) if primes[i] != 0]
a = list(map(int, f.readline().split()))
p = [0] * n
for i in range(n):
	p[a[i] - 1] = i
swaps = []
for i in range(n):
	if p[i] != i:
		r = p[i]
		while r != i:
			j = bisect(primes, r - i) - 1
			l = r - primes[j]
			(p[a[l] - 1], p[a[r] - 1]) = (p[a[r] - 1], p[a[l] - 1])
			(a[l], a[r]) = (a[r], a[l])
			swaps += [(l, r)]
			r = l
print(len(swaps))
if len(swaps) > 0:
	print('\n'.join(('{} {}'.format(l + 1, r + 1) for (l, r) in swaps)))


from sys import stdin
_data = iter(stdin.read().split('\n'))
input = lambda : next(_data)
from bisect import bisect
V = 210000
primes = []
is_prime = [True] * V
is_prime[0] = False
is_prime[1] = False
for i in range(2, V):
	if is_prime[i]:
		primes.append(i)
		for j in range(i + i, V, i):
			is_prime[j] = False
n = int(input())
a = list(map(int, input().split()))
ra = [0] * n
for i in range(n):
	a[i] -= 1
	ra[a[i]] = i
buf = []
p = 0
while p < n:
	while ra[p] != p:
		d = ra[p] - p + 1
		d = primes[bisect(primes, d) - 1] - 1
		r = ra[p]
		q = r - d
		(ra[a[q]], ra[a[r]]) = (ra[a[r]], ra[a[q]])
		(a[q], a[r]) = (a[r], a[q])
		buf.append('{} {}'.format(q + 1, r + 1))
	p += 1
print(len(buf))
print('\n'.join(buf))


n = int(input())
ar = list(map(int, input().split()))
x = 10 ** 5 + 3
seva_nahui_esli_ne_paidet_tebe_pizda = [True] * x
seva_nahui_esli_ne_paidet_tebe_pizda[1] = False
for i in range(2, x):
	if seva_nahui_esli_ne_paidet_tebe_pizda[i]:
		for j in range(i * 2, x, i):
			seva_nahui_esli_ne_paidet_tebe_pizda[j] = False
ans = []
lol = [0] * (n + 1)
for i in range(n):
	lol[ar[i]] = i

def kinda_swap(l, r):
	if l >= r:
		return
	len = r - l + 1
	if seva_nahui_esli_ne_paidet_tebe_pizda[len]:
		(ar[l], ar[r]) = (ar[r], ar[l])
		ans.append([l + 1, r + 1])
		return
	if len % 2 == 0:
		kinda_swap(l, l + 1)
		kinda_swap(l + 1, r)
		kinda_swap(l, l + 1)
		return
	for s in range(2, len + 1):
		if seva_nahui_esli_ne_paidet_tebe_pizda[s] and seva_nahui_esli_ne_paidet_tebe_pizda[r - l - s + 1 + 1]:
			kinda_swap(l, l + s - 1)
			kinda_swap(l + s - 1, r)
			kinda_swap(l, l + s - 1)
			return
for i in range(1, n):
	x = lol[i]
	lol[ar[x]] = i - 1
	lol[ar[i - 1]] = x
	kinda_swap(i - 1, x)
print(len(ans))
for elem in ans:
	print(elem[0], elem[1])


import sys
input = sys.stdin.readline
import bisect
n = int(input())
A = list(map(int, input().split()))
for i in range(n):
	A[i] -= 1
x = 10 ** 5
import math
L = math.floor(math.sqrt(x))
Primelist = [i for i in range(x + 1)]
Primelist[1] = 0
for i in Primelist:
	if i > L:
		break
	if i == 0:
		continue
	for j in range(2 * i, x + 1, i):
		Primelist[j] = 0
Primes = [Primelist[j] - 1 for j in range(x + 1) if Primelist[j] != 0]
A_INV = [-1] * n
for i in range(n):
	A_INV[A[i]] = i
ANS = []
for i in range(n):
	j = A_INV[i]
	while j - i:
		t = bisect.bisect(Primes, j - i) - 1
		sa = Primes[t]
		ANS.append((j - sa, j))
		(A_INV[i], A_INV[A[j - sa]]) = (j - sa, j)
		(A[j], A[j - sa]) = (A[j - sa], A[j])
		j -= sa
print(len(ANS))
for (x, y) in ANS:
	print(x + 1, y + 1)


import sys
import collections as cc
import bisect as bi
input = sys.stdin.readline
I = lambda : list(map(int, input().split()))
pr = []
N = 10 ** 6 + 3
ss = [0] * N
ss[0] = 1
for i in range(2, N):
	if ss[i] == 0:
		ss[i] = i
		pr.append(i)
		for j in range(2 * i, N, i):
			ss[j] = i
(n,) = I()
l = I()
f = {}
ans = 0
an = []
for i in range(n):
	f[l[i]] = i
for i in range(n):
	while l[i] != i + 1:
		ans += 1
		now = f[i + 1]
		dis = now - i + 1
		temp = bi.bisect(pr, dis)
		temp = pr[temp - 1]
		(f[l[now]], f[l[now - temp + 1]]) = (f[l[now - temp + 1]], f[l[now]])
		(l[now - temp + 1], l[now]) = (l[now], l[now - temp + 1])
		an.append([now + 1, now - temp + 2])
print(ans)
for i in an:
	print(*i[::-1])


def prime(n):
	n += 1
	p = [False] * n
	for i in range(3, int(n ** 0.5) + 1, 2):
		(u, v) = (i * i, 2 * i)
		if not p[i]:
			p[u::v] = [True] * ((n - u - 1) // v + 1)
	p[4::2] = [True] * ((n - 3) // 2)
	return p
n = int(input())
t = list(enumerate(list(map(int, input().split())), 1))
t.sort(key=lambda x: x[1])
t = [x[0] for x in t]
(u, v, q) = (list(range(n + 1)), list(range(n + 1)), [])
p = prime(n + 1)
for (i, j) in enumerate(t, 1):
	while i != u[j]:
		k = i
		while p[u[j] - k + 1]:
			k += 1
		q.append(str(k) + ' ' + str(u[j]))
		(a, b) = (u[j], v[k])
		(u[b], u[j], v[a], v[k]) = (a, k, b, j)
print(len(q))
print('\n'.join(q))


from sys import stdin, stdout, setrecursionlimit
from gc import disable
from bisect import bisect_right
gets = input
puts = print
data = iter(stdin.read().split('\n'))
input = lambda : next(data)
print = stdout.write

def RE(n: int) -> list:
	lp = [0] * (n + 1)
	pr = []
	for i in range(2, n + 1):
		if not lp[i]:
			lp[i] = i
			pr.append(i)
		j = 0
		while j < len(pr) and pr[j] <= lp[i] and (i * pr[j] <= n):
			lp[i * pr[j]] = pr[j]
			j += 1
	return pr

def main() -> int:
	disable()
	n = int(input())
	a = list(map(int, input().split()))
	primes = RE(n + 1)
	ans = list()
	arr = [0] * n
	for i in range(n):
		a[i] -= 1
		arr[a[i]] = i
	i = 0
	while i < n:
		while arr[i] != i:
			j = arr[i]
			k = j - i + 1
			k = primes[bisect_right(primes, k) - 1] - 1
			b = arr[i]
			c = b - k
			(arr[a[c]], arr[a[b]]) = (arr[a[b]], arr[a[c]])
			(a[c], a[b]) = (a[b], a[c])
			ans.append((c + 1, b + 1))
		i += 1
	la = len(ans)
	print('%i\n' % la)
	for i in range(la):
		print('%i %i\n' % (ans[i][0], ans[i][1]))
	return 0
main()