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: Accepted)

#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long ull;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const ull mod = 1e9 + 7;
#define REP(i,n) for(int i=0;i<(int)n;++i)

struct edge{
    int to,cap,rev;
};

vector<edge> G[505];
vector<int> check(505, 0);

int dfs(int v, int t, int f){
    if(v==t){return f;}
    check[v]=1;
    for(int i=0;i<G[v].size();i++){
        edge &e = G[v][i];
        if(check[e.to]==0 && e.cap > 0){
            int ff =dfs(e.to,t,min(f,e.cap));
            if(ff>0){
                e.cap -= ff;
                G[e.to][e.rev].cap += ff;
                return ff;
            }
        }
    }
    return 0;
}

int maxflow(int s,int t){
    int flow = 0;
    while(1){
        fill(check.begin(),check.end(),0);
        int f = dfs(s,t,INT_MAX);
        if(f==0){return flow;}
        flow += f;
    }
}

bool prime_check(ll X){
    if(X<2) return false;
    ll sqX = (int)sqrt(X)+1;
    for(int i=2;i<sqX;i++){
        if(X%i==0) return false;
    }
    return true;
}


int main(){
    int N;
    cin >> N;
    ll x[N];
    REP(i, N) cin >> x[i];
    sort(x, x+N);
    vector<ll> koma;
    REP(i, N){
        if(i==0||x[i]!=x[i-1]+1) koma.push_back(x[i]);
        if(i==N-1||x[i+1]!=x[i]+1) koma.push_back(x[i]+1);
    }
    vector<ll> koma_even, koma_odd;
    REP(i, koma.size()){
        if(koma[i]%2==0){
            koma_even.push_back(koma[i]);
        }else{
            koma_odd.push_back(koma[i]);
        }
    }
    REP(i, koma_even.size()){
        REP(j, koma_odd.size()){
            ll dif = abs(koma_even[i]-koma_odd[j]);
            if(prime_check(dif)){
                int v1 = i;
                int v2 = koma_even.size()+j;
                G[v1].push_back((edge){v2, 1, G[v2].size()});
                G[v2].push_back((edge){v1, 0, G[v1].size()-1});
            }
        }
    }
    REP(i, koma_even.size()){
        int v1 = koma_even.size()+koma_odd.size();
        int v2 = i;
        G[v1].push_back((edge){v2, 1, G[v2].size()});
        G[v2].push_back((edge){v1, 0, G[v1].size()-1});
    }
    REP(i, koma_odd.size()){
        int v1 = koma_even.size()+i;
        int v2 = koma_even.size()+koma_odd.size()+1;
        G[v1].push_back((edge){v2, 1, G[v2].size()});
        G[v2].push_back((edge){v1, 0, G[v1].size()-1});
    }

    int N1 = maxflow(koma_even.size()+koma_odd.size(), koma_even.size()+koma_odd.size()+1);
    /*
    printf("N1: %d\n", N1);
    REP(i, koma.size()){
        cout << koma[i] << endl;
    }
    */
    int N2 = (koma_even.size()-N1)/2 + (koma_odd.size()-N1)/2;
    int N3 = (koma_even.size()-N1)%2;
    cout << N1+2*N2+3*N3 << endl;
    return 0;
}