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++ (GCC 9.2.1) (judge verdict: Accepted)

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

#define int long long
#define rep(i, n) for (int i = 0; i < (int) (n); i++)
#define reps(i, n) for (int i = 1; i <= (int) (n); i++)
#define all(x) (x).begin(), (x).end()
#define uniq(x) (x).erase(unique(all(x)), (x).end())
#define bit(n) (1LL << (n))
#define dump(x) cerr << #x " = " << (x) << endl
using vint = vector<int>;
using vvint = vector<vint>;
using pint = pair<int, int>;
using vpint = vector<pint>;
template<typename T> using priority_queue_rev = priority_queue<T, vector<T>, greater<T>>;
constexpr double PI = 3.1415926535897932384626433832795028;
constexpr int DY[9] = {0, 1, 0, -1, 1, 1, -1, -1, 0};
constexpr int DX[9] = {1, 0, -1, 0, 1, -1, -1, 1, 0};
int sign(int x) { return (x > 0) - (x < 0); }
int gcd(int a, int b) {
    while (b) { swap(a %= b, b); }
    return a;
}
int lcm(int a, int b) { return a / gcd(a, b) * b; }
int cdiv(int a, int b) { return (a - 1 + b) / b; }
template<typename T> void fin(T mes) {
    cout << mes << endl;
    exit(0);
}
template<typename T, typename U> bool chmax(T &a, const U &b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template<typename T, typename U> bool chmin(T &a, const U &b) {
    if (b < a) {
        a = b;
        return true;
    }
    return false;
}
template<typename T, typename U> ostream &operator<<(ostream &os, const pair<T, U> &rhs) {
    os << "(" << rhs.first << ", " << rhs.second << ")";
    return os;
}
template<typename T> ostream &operator<<(ostream &os, const vector<T> &rhs) {
    os << "{";
    for (auto itr = rhs.begin(); itr != rhs.end(); itr++) {
        os << *itr << (next(itr) != rhs.end() ? ", " : "");
    }
    os << "}";
    return os;
}
template<typename T> ostream &operator<<(ostream &os, const deque<T> &rhs) {
    os << "{";
    for (auto itr = rhs.begin(); itr != rhs.end(); itr++) {
        os << *itr << (next(itr) != rhs.end() ? ", " : "");
    }
    os << "}";
    return os;
}
template<typename T> ostream &operator<<(ostream &os, const set<T> &rhs) {
    os << "{";
    for (auto itr = rhs.begin(); itr != rhs.end(); itr++) {
        os << *itr << (next(itr) != rhs.end() ? ", " : "");
    }
    os << "}";
    return os;
}
template<typename T, typename U> ostream &operator<<(ostream &os, const map<T, U> &rhs) {
    os << "{";
    for (auto itr = rhs.begin(); itr != rhs.end(); itr++) {
        os << *itr << (next(itr) != rhs.end() ? ", " : "");
    }
    os << "}";
    return os;
}
struct setup {
    static constexpr int PREC = 20;
    setup() {
        cout << fixed << setprecision(PREC);
        cerr << fixed << setprecision(PREC);
    };
} setup;

template<typename M>
struct dinic {
    using T = typename M::T;
    struct edge {
        int to, rev;
        T cap;
        bool is_rev;
    };
    int n;
    std::vector<std::vector<edge>> graph;
    std::vector<int> level, iter;
    void add_edge(int from, int to, T cap) {
        graph[from].push_back({to, (int) graph[to].size(), cap, false});
        graph[to].push_back({from, (int) graph[from].size() - 1, M::id(), true});
    }
    dinic(const std::vector<std::vector<int>> &adj, const std::vector<std::vector<typename M::T>> &cap)
        : n(adj.size()), graph(n), level(n), iter(n) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < adj[i].size(); j++) { add_edge(i, adj[i][j], cap[i][j]); }
        }
    }
    void bfs(int s) {
        fill(level.begin(), level.end(), -1);
        std::queue<int> que;
        level[s] = 0;
        que.push(s);
        while (!que.empty()) {
            int v = que.front();
            que.pop();
            for (int i = 0; i < graph[v].size(); i++) {
                edge &e = graph[v][i];
                if (M::is_id(e.cap) || level[e.to] >= 0) { continue; }
                level[e.to] = level[v] + 1;
                que.push(e.to);
            }
        }
    }
    T dfs(int v, int t, T f) {
        if (v == t) { return f; }
        for (int &i = iter[v]; i < graph[v].size(); i++) {
            edge &e = graph[v][i];
            if (level[v] >= level[e.to] || M::is_id(e.cap)) { continue; }
            T d = dfs(e.to, t, M::gr(f, e.cap) ? e.cap : f);
            if (M::is_id(d)) { continue; }
            e.cap = M::op(e.cap, M::inv(d));
            graph[e.to][e.rev].cap = M::op(graph[e.to][e.rev].cap, d);
            return d;
        }
        return M::id();
    }
    T calc_max_flow(int s, int t, T lim) {
        T ret = M::id();
        while (true) {
            bfs(s);
            if (level[t] < 0 || M::is_id(lim)) { return ret; }
            fill(iter.begin(), iter.end(), 0);
            T f;
            while (!M::is_id(f = dfs(s, t, lim))) {
                ret = M::op(ret, f);
                lim = M::op(lim, M::inv(f));
            }
        }
    }
    T calc_max_flow(int s, int t) { return calc_max_flow(s, t, M::ab()); }
    std::map<std::pair<int, int>, T> get_max_flow() {
        std::map<std::pair<int, int>, T> ret;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < graph[i].size(); j++) {
                edge &e = graph[i][j];
                if (e.is_rev) { ret[{e.to, i}] = e.cap; }
            }
        }
        return ret;
    }
    std::map<std::pair<int, int>, T> get_min_cut(int s) {
        std::map<std::pair<int, int>, T> ret;
        std::vector<int> visited(n);
        std::queue<int> que;
        que.push(s);
        while (!que.empty()) {
            int v = que.front();
            que.pop();
            if (visited[v]) { continue; }
            visited[v] = true;
            for (int i = 0; i < graph[v].size(); i++) {
                edge &e = graph[v][i];
                if (!M::is_id(e.cap)) { que.push(e.to); }
            }
        }
        for (int i = 0; i < n; i++) {
            if (visited[i]) { continue; }
            for (int j = 0; j < graph[i].size(); j++) {
                edge &e = graph[i][j];
                if (e.is_rev && visited[e.to]) { ret[{e.to, i}] = e.cap; }
            }
        }
        return ret;
    }
};

struct int_dinic {
    using T = int;
    static T id() { return 0; }
    static T ab() { return std::numeric_limits<T>::max(); }
    static T inv(const T &a) { return -a; }
    static T op(const T &a, const T &b) { return a + b; }
    static bool gr(const T &a, const T &b) { return a > b; }
    static bool is_id(const T &a) { return a == id(); };
};

std::vector<long long> get_divisors(long long n) {
    std::vector<long long> ret;
    long long i;
    for (i = 1; i * i < n; i++) {
        if (n % i == 0) {
            ret.push_back(i);
            ret.push_back(n / i);
        }
    }
    if (i * i == n) { ret.push_back(i); }
    std::sort(ret.begin(), ret.end());
    return ret;
}

int N;
int x[110];
signed main() {
    cin >> N;
    rep(i, N) { cin >> x[i]; }
    vint v;
    rep(i, N) {
        if (!v.empty() && v.back() == x[i]) { v.pop_back(); }
        else { v.emplace_back(x[i]); }
        v.emplace_back(x[i] + 1);
    }
    vint even, odd;
    rep(i, v.size()) {
        if (v[i] & 1) { odd.emplace_back(v[i]); }
        else { even.emplace_back(v[i]); }
    }
    vvint adj(330), cap(330);
    dinic<int_dinic> dnc(adj, cap);
    rep(i, even.size()) { dnc.add_edge(0, 100 + i, 1); }
    rep(i, odd.size()) { dnc.add_edge(200 + i, 300, 1); }
    rep(i, even.size()) {
        rep(j, odd.size()) {
            if (get_divisors(abs(even[i] - odd[j])).size() == 2) { dnc.add_edge(100 + i, 200 + j, 1); }
        }
    }
    int f = dnc.calc_max_flow(0, 300);
    int ans = v.size() - f;
    if ((even.size() - f) & 1) { ans++; }
    cout << ans << endl;
}