Problem:
Score : 1200 points

Problem Statement

There are infinitely many cards, numbered 1, 2, 3, ...
Initially, Cards x_1, x_2, ..., x_N are face up, and the others are face down.

Snuke can perform the following operation repeatedly:

Select a prime p greater than or equal to 3. Then, select p consecutive cards and flip all of them.

Snuke's objective is to have all the cards face down.
Find the minimum number of operations required to achieve the objective.

Constraints

1 ≤ N ≤ 100

1 ≤ x_1 < x_2 < ... < x_N ≤ 10^7

Input

Input is given from Standard Input in the following format:

N
x_1 x_2 ... x_N

Output

Print the minimum number of operations required to achieve the objective.

Sample Input 1

2
4 5

Sample Output 1

2

Below is one way to achieve the objective in two operations:

Select p = 5 and flip Cards 1, 2, 3, 4 and 5.

Select p = 3 and flip Cards 1, 2 and 3.

Sample Input 2

9
1 2 3 4 5 6 7 8 9

Sample Output 2

3

Below is one way to achieve the objective in three operations:

Select p = 3 and flip Cards 1, 2 and 3.

Select p = 3 and flip Cards 4, 5 and 6.

Select p = 3 and flip Cards 7, 8 and 9.

Sample Input 3

2
1 10000000

Sample Output 3

4

Solution in C++14 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <bits/stdc++.h>

using namespace std;

inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}

const int maxn = 100 + 15;
const int Maxsz = 2e7;
const int inf = 1e9 + 7;

int Dp[maxn][maxn] , n , x[maxn] , Prime[Maxsz + 1] , Primelen , Vis[Maxsz + 1];

void Init(){
	for(int i = 2 ; i <= Maxsz ; ++ i){
		if( !Vis[i] )
			Prime[Primelen ++] = i;
		for(int j = 0 ; j < Primelen && Prime[j] * i <= Maxsz ; ++ j){
			Vis[i * Prime[j]] = 1;
			if( i % Prime[j] == 0 ) break;
		}
	}
}

int Dfs( int l , int r ){
	if( ~Dp[l][r] ) return Dp[l][r];
	int & ans = Dp[l][r] = inf;
	if( l > r ) return ans = 0;
	if( l == r ) return ans = 3;
	int ret = 0;
	for(int i = l + 1 ; i <= r ; ++ i){
		if( x[i] - x[i - 1] - 1 == 0 ) ret += 0;
		else if( x[i] - x[i - 1] - 1 == 1 ) ret += 3;
		else if( x[i] - x[i - 1] - 1 == 2 ) ret += 2;
		else if( Vis[ x[i] - x[i - 1] - 1 ] == 0 ) ret += 1;
		else ret += 2;
	}
	int length = x[r] - x[l] + 1;
	if( length == 2 ) ret += 2;
	else if( Vis[length] == 0 ) ret += 1;
	else if( length & 1 ) ret += 3;
	else ret += 2;
	for(int i = l ; i <= r ; ++ i)
		for(int j = i ; j <= r ; ++ j)
			ans = min( ans , Dfs( l , i - 1 ) + Dfs( i , j ) + Dfs( j + 1 , r ) );
	return ans = min( ans , ret );
}

int main( int argc , char * argv[] ){
	Init();
	n = read();
	for(int i = 1 ; i <= n ; ++ i)
		x[i] = read();
	memset( Dp , -1 , sizeof( Dp ) );
	printf( "%d\n" , Dfs( 1 , n ) );
	return 0;
}