#include <bits/stdc++.h>   using namespace std;   const int NMAX = 210, INF = 0x3f3f3f3f, VMAX = 20010;   int N, A[NMAX], Source, Sink, Flow[NMAX][NMAX], Cap[NMAX][NMAX], Father[NMAX],       Even, Odd;   bool Used[NMAX], Prime[VMAX];   vector<int> G[NMAX], FlowG[NMAX], CurrentTable;   vector<vector<int> > Ans;   bool BFS() {     queue<int> Q;     for (int i = 0; i <= N + 1; ++i) Used[i] = Father[i] = 0;     Used[Source] = 1;     Q.push(Source);     while (!Q.empty()) {       int Node = Q.front();       Q.pop();       if (Node == Sink) return 1;       for (int i = 0; i < G[Node].size(); ++i) {         int Vec = G[Node][i];         if (!Used[Vec] && Cap[Node][Vec] > Flow[Node][Vec])           Used[Vec] = 1, Father[Vec] = Node, Q.push(Vec);       }     }     return Used[Sink];   }   void DFS(int Node, int StartNode) {     if (Node == StartNode && CurrentTable.size() >= 3) return;     CurrentTable.push_back(Node);     Used[Node] = 1;     for (int i = 0; i < FlowG[Node].size(); ++i)       if (!Used[FlowG[Node][i]]) DFS(FlowG[Node][i], StartNode);   }   void BuildGraph() {     Source = 0;     Sink = N + 1;     for (int i = 1; i <= N; ++i)       if (A[i] % 2 == 1) {         G[Source].push_back(i);         G[i].push_back(Source);         Cap[Source][i] = 2;       } else {         G[i].push_back(Sink);         G[Sink].push_back(i);         Cap[i][Sink] = 2;       }     for (int i = 1; i <= N; ++i)       for (int j = 1; j <= N; ++j)         if (A[i] % 2 == 1 && A[j] % 2 == 0 && Prime[A[i] + A[j]]) {           G[i].push_back(j);           G[j].push_back(i);           Cap[i][j] = 1;         }   }   void MaxFlow() {     int CntFlow = 0;     while (BFS()) {       for (int i = 0; i < G[Sink].size(); ++i) {         int Vec = G[Sink][i];         if (Used[Vec] && Cap[Vec][Sink] != Flow[Vec][Sink]) {           int MinFlow = INF;           Father[Sink] = Vec;           for (int Node = Sink; Node != Source; Node = Father[Node])             MinFlow =                 min(MinFlow, Cap[Father[Node]][Node] - Flow[Father[Node]][Node]);           for (int Node = Sink; Node != Source; Node = Father[Node]) {             Flow[Father[Node]][Node] += MinFlow;             Flow[Node][Father[Node]] -= MinFlow;           }           CntFlow += MinFlow;         }       }     }     if (CntFlow != N)       printf( Impossible n );     else {       for (int i = 1; i <= N; ++i)         for (int j = 1; j <= N; ++j)           if (A[i] % 2 == 1 && A[j] % 2 == 0 && Prime[A[i] + A[j]] &&               Flow[i][j] == 1)             FlowG[i].push_back(j), FlowG[j].push_back(i);       for (int i = 1; i <= N; ++i) Used[i] = 0;       for (int i = 1; i <= N; ++i)         if (!Used[i]) {           CurrentTable.clear();           DFS(i, i);           Ans.push_back(CurrentTable);         }       printf( %i n , Ans.size());       for (int i = 0; i < Ans.size(); ++i) {         printf( %i  , Ans[i].size());         for (int j = 0; j < Ans[i].size(); ++j) printf( %i  , Ans[i][j]);         printf(  n );       }       return;     }   }   int main() {     for (int i = 2; i < VMAX; ++i) Prime[i] = 1;     for (int i = 2; i < VMAX; ++i)       if (Prime[i])         for (int j = i + i; j < VMAX; j += i) Prime[j] = 0;     scanf( %i , &N);     for (int i = 1; i <= N; ++i) {       scanf( %i , &A[i]);       Even += (A[i] % 2 == 0);       Odd += (A[i] % 2 == 1);     }     if (Even != Odd) {       printf( Impossible n );       return 0;     }     BuildGraph();     MaxFlow();     return 0;   }