#include <bits/stdc++.h>   #pragma GCC optimize( -O2 )   using namespace std;   void err(istream_iterator<string> it) {}   template <typename T, typename... Args>   void err(istream_iterator<string> it, T a, Args... args) {     cerr << *it <<   =   << a << endl;     err(++it, args...);   }   const int LIM = 1e5 + 5, MOD = 1e9 + 7;   int t, n, m, k, x, y;   int is_com[LIM];   vector<int> pr;   void sieve() {     is_com[1] = 1;     for (int i = 2; i < LIM; i++) {       if (!is_com[i]) {         pr.push_back(i);         for (int j = i + i; j < LIM; j += i) {           is_com[j] = 1;         }       }     }   }   struct edge {     int from, to, cap, flow, index;     edge(int from, int to, int cap, int flow, int index)         : from(from), to(to), cap(cap), flow(flow), index(index) {}   };   struct PushRelabel {     int n;     vector<vector<edge> > g;     vector<long long> excess;     vector<int> height, active, count;     queue<int> Q;     PushRelabel(int n)         : n(n), g(n), excess(n), height(n), active(n), count(2 * n) {}     void addEdge(int from, int to, int cap) {       g[from].push_back(edge(from, to, cap, 0, g[to].size()));       if (from == to) g[from].back().index++;       g[to].push_back(edge(to, from, 0, 0, g[from].size() - 1));     }     void enqueue(int v) {       if (!active[v] && excess[v] > 0) {         active[v] = true;         Q.push(v);       }     }     void push(edge &e) {       int amt = (int)min(excess[e.from], (long long)e.cap - e.flow);       if (height[e.from] <= height[e.to] || amt == 0) return;       e.flow += amt;       g[e.to][e.index].flow -= amt;       excess[e.to] += amt;       excess[e.from] -= amt;       enqueue(e.to);     }     void relabel(int v) {       count[height[v]]--;       int d = 2 * n;       for (auto &it : g[v]) {         if (it.cap - it.flow > 0) d = min(d, height[it.to] + 1);       }       height[v] = d;       count[height[v]]++;       enqueue(v);     }     void gap(int k) {       for (int v = 0; v < n; v++) {         if (height[v] < k) continue;         count[height[v]]--;         height[v] = max(height[v], n + 1);         count[height[v]]++;         enqueue(v);       }     }     void discharge(int v) {       for (int i = 0; excess[v] > 0 && i < g[v].size(); i++) push(g[v][i]);       if (excess[v] > 0) {         if (count[height[v]] == 1)           gap(height[v]);         else           relabel(v);       }     }     long long max_flow(int source, int dest) {       count[0] = n - 1;       count[n] = 1;       height[source] = n;       active[source] = active[dest] = 1;       for (auto &it : g[source]) {         excess[source] += it.cap;         push(it);       }       while (!Q.empty()) {         int v = Q.front();         Q.pop();         active[v] = false;         discharge(v);       }       long long max_flow = 0;       for (auto &e : g[source]) max_flow += e.flow;       return max_flow;     }   };   vector<vector<int> > v, ans;   vector<int> vs;   void dfs(int i, int c) {     vs[i] = 1;     ans[c].push_back(i + 1);     for (auto &it : v[i]) {       if (!vs[it]) dfs(it, c);     }   }   int main() {     ios_base::sync_with_stdio(false);     cin.tie(0);     cout.tie(0);     sieve();     cin >> n;     vector<int> odd, even;     vector<int> indodd, indeven;     for (int i = 0; i < n; i++) {       cin >> x;       if (x & 1)         odd.push_back(x), indodd.push_back(i);       else         even.push_back(x), indeven.push_back(i);     }     if (odd.size() != even.size()) {       cout <<  Impossible n ;       return 0;     }     PushRelabel p(n + 2);     for (int i = 0; i < even.size(); i++) {       p.addEdge(odd.size() + 1 + i, n + 1, 2);     }     for (int i = 0; i < odd.size(); i++) {       p.addEdge(0, i + 1, 2);       for (int j = 0; j < even.size(); j++) {         if (!is_com[odd[i] + even[j]]) {           p.addEdge(i + 1, j + 1 + odd.size(), 1);         }       }     }     int ans1 = p.max_flow(0, n + 1);     if (ans1 == n) {       v.assign(n, vector<int>(0));       for (int i = 0; i < odd.size(); i++) {         for (auto &it : p.g[i + 1]) {           if (it.flow == 1) {             x = indodd[i];             y = indeven[it.to - 1 - odd.size()];             v[x].push_back(y);             v[y].push_back(x);           }         }       }       vs.assign(n, 0);       int c = 0;       for (int i = 0; i < n; i++) {         if (!vs[i]) ans.push_back(vector<int>(0)), dfs(i, c), c++;       }       cout << c <<   n ;       for (auto &it : ans) {         cout << it.size() <<    ;         for (auto &it1 : it) {           cout << it1 <<    ;         }         cout <<   n ;       }     } else       cout <<  Impossible n ;     return 0;   }