#include <stdio.h>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <climits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
// #include <unordered_map>
#include <cassert>

#define SHOW(...) {;}
#define REACH_HERE {;}
#undef HHHDEBUG
#ifdef HHHDEBUG
#include "template.h"
#endif

using namespace std;

const int HH = 205;
const int JJ = 500000;

const int MAXFOX = 203;
int n;
int fox[MAXFOX];
int n_odd;
int fox_odd[MAXFOX];
int n_even;
int fox_even[MAXFOX];
int total_n;

struct Edge {
	int from;
	int to;
	int cap;
};

int source, sink;
vector<int> g[HH];
int cap[HH][HH];
int lv[HH];

bool mark_level(int start, int end) {
    memset(lv, -1, sizeof(lv));
    queue<int> q;
    lv[start] = 0;
    q.push(start);
    while (!q.empty()) {
        int cur = q.front(); q.pop();
        for (int i = 0; i < g[cur].size(); ++i) {
        	int next = g[cur][i];
            if (cap[cur][next] != 0 && lv[next] == -1) {
                lv[next] = lv[cur] + 1;
                q.push(next);
            }
        }
    }
    return lv[end] != -1;
}

int augment(int cur, int end, int min_flow) {
    if (cur == end)
        return min_flow;

    int augmented_flow = 0;
    for (int i = 0; i < g[cur].size(); i++) {
    	int next = g[cur][i];
    	if ((lv[next] == lv[cur] + 1 && cap[cur][next] > 0) &&
            (augmented_flow = augment(next, end, min(cap[cur][next], min_flow)))
        ) {
            cap[cur][next] -= augmented_flow;
            cap[next][cur] += augmented_flow;
            return augmented_flow;
        }
    }
    return 0;
}

int dinic(int start, int end) {
	int total = 0;
	int flow = 0;
    while (mark_level(start, end))
        while (flow = augment(start, end, INT_MAX))
        	total += flow;
    return total;
}

void show_cap() {
		printf(" x:");
		for (int j = 0; j < total_n; j++)
			printf(" %3d", j);
		printf("\n");
	for (int i = 0; i < total_n; i++) {
		printf("%2d:", i);
		for (int j = 0; j < total_n; j++)
			printf(" %d/%d", cap[i][j], cap[j][i]);
		printf("\n");
	}
}

bool is_prime(int n) {
    if (n == 1 || n % 2 == 0)
        return false;
    int t = sqrt(n);
    for (int i = 3; i <= t; i += 2)
        if (n % i == 0)
            return false;
    return true;
}

void build_graph() {
	total_n = n + 2;
	source = 0;
	sink = total_n - 1;
	for (int i = 0; i < n_odd; i++) {
		int fox_index = fox_odd[i];
		cap[source][fox_index] = 2;
		g[source].push_back(fox_index);
		g[fox_index].push_back(source);
		SHOW("ADD EDGE", source, i, fox_index);
	}
	for (int i = 0; i < n_even; i++) {
		int fox_index = fox_even[i];
		cap[fox_index][sink] = 2;
		g[fox_index].push_back(sink);
		g[sink].push_back(fox_index);
		SHOW("ADD EDGE", fox_index, sink);
	}
	for (int i = 0; i < n_odd; i++) {
		for (int j = 0; j < n_even; j++) {
			int fox_index_odd = fox_odd[i];
			int fox_index_even = fox_even[j];
			if (is_prime(fox[fox_index_odd] + fox[fox_index_even])) {
				cap[fox_index_odd][fox_index_even] = 1;
				g[fox_index_odd].push_back(fox_index_even);
				g[fox_index_even].push_back(fox_index_odd);
				SHOW("ADD EDGE", fox_index_odd, fox_index_even);
			}
		}
	}
	SHOW(n, n_odd, n_even, total_n, source, sink)
}

bool printed[HH];

vector<int> cur_ans;

int n_table;
stringstream ans;

void print_cur(int a) {
	SHOW(a)
	cur_ans.push_back(a);
	printed[a] = true;
	for (int i = 0; i < g[a].size(); i++) {
		int next = g[a][i];
		if (next != source && next != sink && !printed[next]) {
			SHOW(a, next, fox[a], fox[next], fox[a] % 2, cap[a][next])
			if (fox[a] % 2 == 1 && cap[a][next] == 0) {
				print_cur(next);
				return ;
			}
			else if (fox[a] % 2 == 0 && cap[a][next] == 1) {
				print_cur(next);
				return ;
			}
		}
	}
}

void print_ans() {
	for (int j = 1; j <= n; j++) {
		if (printed[j] == false) {
			n_table++;
			SHOW(j, n_table)
			cur_ans.clear();
			print_cur(j);
			ans << cur_ans.size();
			SHOW(cur_ans.size())
			// for (int x : cur_ans)
			// 	ans << " " << x;
			for (int i = 0; i < cur_ans.size(); i++)
				ans << " " << cur_ans[i];
			ans << endl;
			SHOW(ans.str())
		}
	}
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> fox[i];
		if (fox[i] % 2) {
			fox_odd[n_odd] = i;
			n_odd++;
		}
		else {
			fox_even[n_even] = i;
			n_even++;
		}
	}
	// printf("odd:");
	// for (int i = 0; i < n_odd; i++)
	// 	printf(" %d", fox_odd[i]);
	// printf("\n");
	// printf("even:");
	// for (int i = 0; i < n_even; i++)
	// 	printf(" %d", fox_even[i]);
	// printf("\n");

	memset(g, 0, sizeof(g));
	build_graph();
	// show_cap();
	int total_flow = dinic(source, sink);
	// cout << endl;
	// show_cap();
	// printf("tf: %d\n", total_flow);
	SHOW(total_flow)
	if (total_flow == n) {
		print_ans();
		cout << n_table << endl;
		cout << ans.str();
	}
	else
		cout << "Impossible" << endl;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=200+50;
const int MAXN=40000+50;
const int inf=0x3fffffff;
const double eps=1e-8;
const int mod=100000000+7;
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define PII pair<int, int>
#define mk(x,y) make_pair((x),(y))
int n,edge_cnt,top,cnt;
int a[N],head[N],vis[N],que[N],cur[N],s[N],gap[N],dep[N],num[N];
vector<int>mp[N];
struct Edge{
    int u,v,cap,flow,next;
}edge[MAXN];
void init(){
    edge_cnt=top=0;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++)
        mp[i].clear();
}
void addedge(int u,int v,int cap){
    edge[edge_cnt].u=u; edge[edge_cnt].v=v;
    edge[edge_cnt].cap=cap; edge[edge_cnt].flow=0;
    edge[edge_cnt].next=head[u]; head[u]=edge_cnt++;
    edge[edge_cnt].u=v; edge[edge_cnt].v=u;
    edge[edge_cnt].cap=0; edge[edge_cnt].flow=0;
    edge[edge_cnt].next=head[v]; head[v]=edge_cnt++;
}
void bfs(int st,int ed){
    memset(gap,0,sizeof(gap));
    memset(dep,-1,sizeof(dep));
    int front=0,rear=0;
    gap[0]=1; dep[ed]=0; que[rear++]=ed;
    while(front!=rear){
        int u=que[front++];
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(dep[v]!=-1)
                continue;
            que[rear++]=v;
            dep[v]=dep[u]+1; gap[dep[v]]++;
        }
    }
}
int isap(int st,int ed){
    bfs(st,ed);
    memcpy(cur,head,sizeof(head));
    int ans=0,u=st;
    while(dep[st]<n+2){
        if(u == ed){
            int Min=inf,inser;
            for(int i=0;i<top;i++){
                if(edge[s[i]].cap-edge[s[i]].flow<Min){
                    Min=edge[s[i]].cap-edge[s[i]].flow;
                    inser=i;
                }
            }
            for(int i=0;i<top;i++)
                edge[s[i]].flow+=Min,edge[s[i]^1].flow-=Min;
            ans+=Min; top=inser;
            u=edge[s[top]^1].v;
            continue;
        }
        int flag=0,v;
        for(int i=cur[u];i!=-1;i=edge[i].next){
            v=edge[i].v;
            if(edge[i].cap-edge[i].flow>0 && dep[v]+1 == dep[u]){
                flag=1; cur[u]=i;
                break;
            }
        }
        if(flag){
            s[top++]=cur[u]; u=v;
            continue;
        }
        int d=n+2;
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(edge[i].cap-edge[i].flow>0 && dep[v]<d)
                cur[u]=i,d=dep[v];
        }
        gap[dep[u]]--;
        if(!gap[dep[u]]) return ans;
        dep[u]=d+1; gap[dep[u]]++;
        if(u!=st)
            u=edge[s[--top]^1].v;
    }
    return ans;
}
bool ok(int x){
    int flag=1;
    for(int i=2;i*i<=x;i++){
        if((x%i) == 0){
            flag=0;
            break;
        }
    }
    return flag;
}
void dfs(int u){
    num[++cnt]=u;
    for(int i=0;i<mp[u].size();i++){
        int v=mp[u][i];
        if(vis[v])
            continue;
        vis[v]=1;
        dfs(v);
    }
}
int main(){
    //freopen("in.txt","r",stdin);
    while(~scanf("%d",&n)){
        init();
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++){
            if(a[i]&1)
                addedge(0,i,2);
            else
                addedge(i,n+1,2);
        }
        for(int i=1;i<=n;i++){
            if((a[i]&1) == 0)
                continue;
            for(int j=1;j<=n;j++){
                if(a[j]&1)
                    continue;
                if(ok(a[i]+a[j]))
                    addedge(i,j,1);
            }
        }
        int ans=isap(0,n+1);
        if(ans!=n){
            printf("Impossible\n");
            continue;
        }
        for(int i=0;i<edge_cnt;i++){
            if(edge[i].u>0 && edge[i].u<n+1 && edge[i].v>0 && edge[i].v<n+1){
                int u=edge[i].u,v=edge[i].v;
                if((a[u]&1) && edge[i].cap-edge[i].flow == 0){
                    mp[u].push_back(v); mp[v].push_back(u);
                }
            }
        }
        int count=0;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
            if(!vis[i]){
                ++count;
                vis[i]=1;
                dfs(i);
            }
        printf("%d\n",count);
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                cnt=0;
                vis[i]=1;
                dfs(i);
            printf("%d",cnt);
            for(int j=1;j<=cnt;j++)
                printf(" %d",num[j]);
            printf("\n");
            }
        }
    }
    return 0;
}


#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
struct node
{
    int from;
    int to;
    int w;
    int next;
}e[1515151];
vector<int >mp[2050];
int vis[2050];
int head[2050];
int cur[2050];
int divv[2050];
int lx[2050];
int ly[2050];
int a[205];
int Is_or[165550];//0????
int n,cont,ss,tt,contx,conty;
void add(int from,int to,int w)
{
    e[cont].from=from;
    e[cont].to=to;
    e[cont].w=w;
    e[cont].next=head[from];
    head[from]=cont++;
}
void init()
{
    memset(Is_or,0,sizeof(Is_or));
    for(int j=2;j<sqrt(165540);j++)
    {
        if(Is_or[j]==0)
        for(int k=j+j;k<=165540;k+=j)
        Is_or[k]=1;
    }
}
void getmap()
{
    cont=0;
    ss=n+1;
    tt=ss+1;
    contx=0,conty=0;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++)
    {
        if(a[i]%2==0)
        {
            add(ss,i,2);
            add(i,ss,0);
            lx[contx++]=i;
        }
        else
        {
            add(i,tt,2);
            add(tt,i,0);
            ly[conty++]=i;
        }
    }
    for(int i=0;i<contx;i++)
    {
        for(int j=0;j<conty;j++)
        {
            if(Is_or[a[lx[i]]+a[ly[j]]]==0)
            {
                add(lx[i],ly[j],1);
                add(ly[j],lx[i],0);
            }
        }
    }
}
int makedivv()
{
    queue<int >s;
    s.push(ss);
    memset(divv,0,sizeof(divv));
    divv[ss]=1;
    while(!s.empty())
    {
        int u=s.front();
        if(u==tt)return 1;
        s.pop();
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            int w=e[i].w;
            if(w&&divv[v]==0)
            {
                divv[v]=divv[u]+1;
                s.push(v);
            }
        }
    }
    return 0;
}
int Dfs(int u,int maxflow,int tt)
{
    if(u==tt)return maxflow;
    int ret=0;
    for(int &i=cur[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        int w=e[i].w;
        if(w&&divv[v]==divv[u]+1)
        {
            int f=Dfs(v,min(maxflow-ret,w),tt);
            e[i].w-=f;
            e[i^1].w+=f;
            ret+=f;
            if(ret==maxflow)return ret;
        }
    }
    return ret;
}
int Dinic()
{
    int ans=0;
    while(makedivv()==1)
    {
        memcpy(cur,head,sizeof(head));
        ans+=Dfs(ss,0x3f3f3f3f,tt);
    }
    return ans;
}
void Dfss(int u,int tot)
{
    mp[tot].push_back(u);
    vis[u]=1;
    for(int i=head[u];i!=-1;i=e[i].next)
    {
        int v=e[i].to;
        if(vis[v]==1)continue;
        int w=e[i].w;
        if(v!=ss&&v!=tt)
        {
            if(i%2==0&&w==0)
            {
                Dfss(v,tot);
            }
            if(i%2==1&&e[i^1].w==0)
            {
                Dfss(v,tot);
            }
        }
    }
}
int main()
{
    init();
    while(~scanf("%d",&n))
    {
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            mp[i].clear();
        }
        getmap();
        int tmp=Dinic();
        if(tmp==n)
        {
            int tot=0;
            for(int i=1;i<=n;i++)
            {
                if(vis[i]==0)
                {
                    Dfss(i,++tot);
                }
            }
            printf("%d\n",tot);
            for(int i=1;i<=tot;i++)
            {
                printf("%d",mp[i].size());
                for(int j=0;j<mp[i].size();j++)
                {
                    printf(" %d",mp[i][j]);
                }
                printf("\n");
            }
        }
        else printf("Impossible\n");
    }
}


#include<bits/stdc++.h>
#define MAX_V 205
#define INF 1000000000
using namespace std;
typedef vector<int> vi;
typedef vector<list<int> > vli;
int N,s,t,f,mf,odd,even;
vli sol;
int a[MAX_V]={0};
int  res[MAX_V][MAX_V]={0};
bool ori[MAX_V][MAX_V]={0};
bitset<MAX_V> used;
vi p;
bool isPrime(int i){
	if(i<2) return false;
	if(i==2) return true;
	for(int x=3; x*x <= i; x+=2){
		if(i%x == 0) return false;
	}
	return true;
}
void augment(int v, int minEdge) { // traverse BFS spanning tree from s->t
	if (v == s) {
		f = minEdge;
		return;
	} // record minEdge in a global var f
	else if (p[v] != -1) { augment(p[v], min(minEdge, res[p[v]][v])); res[p[v]][v] -= f; res[v][p[v]] += f; }
}
bool tryFlow(){
	s = 0, t = N+1;
	for(int i=1;i<=N;i++){
		if(a[i]%2==0){
			res[s][i] = 2;
			ori[s][i] = true;
		}else{
			res[i][t] = 2;
			ori[i][t] = true;
		}
		for(int j=1;j<i;j++){
			if(a[i]%2 == a[j]%2) continue;
			if(isPrime(a[i]+a[j])){
				if(a[i]%2 == 0)
					ori[i][j] = res[i][j] =  1;
				else
					ori[j][i] = res[j][i] =  1;
			}
		}
	}
	mf = 0;
	while (1) {
		f = 0;
		vi dist(MAX_V, INF); dist[s] = 0; queue<int> q; q.push(s);
		p.assign(MAX_V, -1);
		while (!q.empty()) {
			int u = q.front(); q.pop();
			if (u == t) break;
			for (int v = 0; v < MAX_V; v++)
				if (res[u][v] > 0 && dist[v] == INF)
					dist[v] = dist[u] + 1, q.push(v), p[v] = u;
		}
		augment(t, INF);
		if (f == 0) break;
		mf += f;
	}
	if(mf != 2*odd) return false;
	return true;
}
void agregar(int u, int idx, bool left, bool even){
	used[u] = true;
	if(even){
		for(int i=1;i<=N;i++){
			if(!ori[i][u] && res[i][u]>0 && !used[i]){
				if(left)
					sol[idx].push_front(i);
				else
					sol[idx].push_back(i);
				agregar(i,idx,left,!even);
			}
		}
	}else{
		for(int i=1;i<=N;i++){
			if(!ori[u][i] && res[u][i]>0 && !used[i]){
				if(left)
					sol[idx].push_front(i);
				else
					sol[idx].push_back(i);
				agregar(i,idx,left,!even);
			}
		}
	}

}
int main(){
	odd=0, even=0;
	cin>>N;
	for(int i=1;i<=N;i++){
		cin>>a[i];
		if(a[i]%2 == 0) even++;
		else odd++;
	}
	if(even != odd || !tryFlow()){
		cout<<"Impossible\n";
	}else{
		int tables = 0;
		for(int j=1;j<=N;j++){
			if(res[t][j]==2 && !used[j]){
				list<int> lista;
				lista.push_back(j);
				sol.push_back(lista);
				agregar(j,tables,true,false);
				agregar(j,tables++,false,false);
			}
		}
		cout<<sol.size()<<'\n';
		list<int>::iterator it;
		for(int i=0;i<sol.size();i++){
			cout<<sol[i].size();
			for(it = sol[i].begin(); it!=sol[i].end();it++){
				cout<<' '<<(*it);
			}
			cout<<'\n';
		}
	}
	return 0;
}


#include<bits/stdc++.h>
#define MAX_V 205
#define INF 1000000000
using namespace std;
typedef vector<int> vi;
typedef vector<list<int> > vli;
int N,s,t,f,mf,odd,even;
vli sol;
int a[MAX_V]={0};
int  res[MAX_V][MAX_V]={0};
bool ori[MAX_V][MAX_V]={0};
bitset<MAX_V> used;
vi p;
bool isPrime(int i){
	if(i<2) return false;
	if(i==2) return true;
	for(int x=3; x*x <= i; x+=2){
		if(i%x == 0) return false;
	}
	return true;
}
void augment(int v, int minEdge) { // traverse BFS spanning tree from s->t
	if (v == s) {
		f = minEdge;
		return;
	} // record minEdge in a global var f
	else if (p[v] != -1) { augment(p[v], min(minEdge, res[p[v]][v])); res[p[v]][v] -= f; res[v][p[v]] += f; }
}
bool tryFlow(){
	s = 0, t = N+1;
	for(int i=1;i<=N;i++){
		if(a[i]%2==0){
			res[s][i] = 2;
			ori[s][i] = true;
		}else{
			res[i][t] = 2;
			ori[i][t] = true;
		}
		for(int j=1;j<i;j++){
			if(a[i]%2 == a[j]%2) continue;
			if(isPrime(a[i]+a[j])){
				if(a[i]%2 == 0)
					ori[i][j] = res[i][j] =  1;
				else
					ori[j][i] = res[j][i] =  1;
			}
		}
	}
	mf = 0;
	while (1) {
		f = 0;
		vi dist(MAX_V, INF); dist[s] = 0; queue<int> q; q.push(s);
		p.assign(MAX_V, -1);
		while (!q.empty()) {
			int u = q.front(); q.pop();
			if (u == t) break;
			for (int v = 0; v < MAX_V; v++)
				if (res[u][v] > 0 && dist[v] == INF)
					dist[v] = dist[u] + 1, q.push(v), p[v] = u;
		}
		augment(t, INF);
		if (f == 0) break;
		mf += f;
	}
	if(mf != 2*odd) return false;
	return true;
}
void agregar(int u, int idx, bool left, bool even){
	used[u] = true;
	if(even){
		for(int i=1;i<=N;i++){
			if(!ori[i][u] && res[i][u]>0 && !used[i]){
				if(left)
					sol[idx].push_front(i);
				else
					sol[idx].push_back(i);
				agregar(i,idx,left,!even);
			}
		}
	}else{
		for(int i=1;i<=N;i++){
			if(!ori[u][i] && res[u][i]>0 && !used[i]){
				if(left)
					sol[idx].push_front(i);
				else
					sol[idx].push_back(i);
				agregar(i,idx,left,!even);
			}
		}
	}

}
int main(){
	ios_base::sync_with_stdio(false); cin.tie(0);
	odd=0, even=0;
	cin>>N;
	for(int i=1;i<=N;i++){
		cin>>a[i];
		if(a[i]%2 == 0) even++;
		else odd++;
	}
	if(even != odd || !tryFlow()){
		cout<<"Impossible\n";
	}else{
		int tables = 0;
		for(int j=1;j<=N;j++){
			if(res[t][j]==2 && !used[j]){
				list<int> lista;
				lista.push_back(j);
				sol.push_back(lista);
				agregar(j,tables,true,false);
				agregar(j,tables++,false,false);
			}
		}
		cout<<sol.size()<<'\n';
		list<int>::iterator it;
		for(int i=0;i<sol.size();i++){
			cout<<sol[i].size();
			for(it = sol[i].begin(); it!=sol[i].end();it++){
				cout<<' '<<(*it);
			}
			cout<<'\n';
		}
	}
	return 0;
}


#include <bits/stdc++.h>
#define NO { cout << "Impossible"; exit(0); }
#define pb push_back

using namespace std;

const int maxn = 201, val = 2e4;
int Val[maxn+1], n, C[maxn+1][maxn+1], F[maxn+1][maxn+1], Prime[val+1], X[val+1], num, ans, D[maxn+1], Free[maxn+1];
bool P[val+1], Ok[maxn+1];
vector <int> A[maxn+1], res[maxn+1];

Input()
{
    cin >> n;
    int d = 0;
    for (int i=1; i<=n; i++)
    {
        cin >> Val[i];
        if (Val[i] % 2) d++, A[0].pb(i), A[i].pb(0), C[0][i] = 2;
        else A[n+1].pb(i), A[i].pb(n+1), C[i][n+1] = 2;
    }
    if (d != n/2) NO
}

void PRIME()
{
    memset(P, 0, sizeof(P));
    for (int i=2; i<=val; i++)
    {
        if (!X[i]) P[i] = 1, X[i] = Prime[++num] = i;
        for (int j=1; j <= num && Prime[j] <= X[i] && Prime[j] * i <= val; j++) X[Prime[j]*i] = Prime[j];
    }
}

void Built()
{
    for (int i=1; i<=n; i++)
        if (Val[i] % 2)
            for (int j=1; j<=n; j++)
                if (!(Val[j] % 2))
                    if (P[Val[i] + Val[j]]) A[i].pb(j), A[j].pb(i), C[i][j] = 1;
}

bool BFS()
{
    queue <int> Q;
    Q.push(0);
    memset(D, 0, sizeof(D));
    D[0] = 1;
    while (Q.size())
    {
        int u = Q.front();
        Q.pop();
        if (u == n+1) return 1;
        for (int i=0; i<A[u].size(); i++)
        {
            int v = A[u][i];
            if (C[u][v] > F[u][v] && !D[v]) D[v] = D[u] + 1, Q.push(v);
        }
    }
    return 0;
}

int DFS(int u, int Min)
{
    if (u == n+1) return Min;
    if (Free[u] == num) return 0;
    else Free[u] = num;
    for (int i=0; i<A[u].size(); i++)
    {
        int v = A[u][i];
        if (C[u][v] > F[u][v])
            if (D[v] == D[u] + 1 && Free[v] != num)
                if (int x = DFS(v, min(Min, C[u][v] - F[u][v])))
                {
                    F[u][v] += x;
                    F[v][u] -= x;
                    return x;
                }
    }
    return 0;
}

void Flow()
{
    int x;
    while (BFS())
        while (++num, x = DFS(0, 1e9)) ans += x;
    if (ans != n) NO
}

void Dfs(int u, int x)
{
    Ok[u] = 0;
    res[ans].pb(u);
    for (int i=0; i<A[u].size(); i++)
    {
        int v = A[u][i];
        if (v < 1 || v > n) continue;
        if (Ok[v] && F[u][v] == x) Dfs(v, -x);
    }
}

void Tract()
{
    memset(Ok, 1, sizeof(Ok));
    ans = 0;
    for (int i=1; i<=n; i++)
        if (Val[i] % 2 && Ok[i]) ans++, Dfs(i, 1);
}

void Output()
{
    cout << ans << "\n";
    for (int i=1; i<=ans; i++)
    {
        cout << res[i].size() << " ";
        for (int j=0; j<res[i].size(); j++) cout << res[i][j] << " ";
        cout << "\n";
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(NULL); cout.tie(NULL);
    Input();
    PRIME();
    Built();
    Flow();
    Tract();
    Output();
    return 0;
}


#include <iostream>
#include <vector>
#include <utility>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <cstdio>
using namespace std;
const int MAXN = 205;
const int MAXP = 20006;
const int inf = 1000000007;

int lp[MAXP] = {0};
vector <int> primes;

void getPrimes()
{
    for ( int i = 2; i < MAXP; i++)
    {
        if ( lp[i] == 0 )
        {
            lp[i] = i;
            primes.push_back( i );
        }

        for ( int j = 0; j < primes.size() && primes[j] <= lp[i] && i * primes[j] < MAXP; j++)
            lp[ i * primes[j] ] = primes[j];
    }
}

int a[MAXN];
int G[MAXN][MAXN] = {0} , Aug[MAXN][MAXN] = {0};
vector <int> p[MAXN];

bool been[MAXN];
int last[MAXN] , MinOnPath[MAXN];
queue <int> Q;

bool AugmentationSucceeded( int N )
{
    for (int i = 1; i <= N; i++)
    {
        been[i] = false;
        last[i] = 0;
        MinOnPath[i] = inf;
    }

    while ( Q.size() != 0 ) Q.pop();

    been[1] = true;
    Q.push( 1 );

    int u;
    while ( Q.size() != 0 )
    {
        u = Q.front(); Q.pop();
        if ( u == N ) break;

        for ( int i = 0; i < p[u].size(); i++)
        {
            int v = p[u][i];
            if ( !been[v] && Aug[u][v] > 0 )
            {
                been[v] = true;
                last[v] = u;
                MinOnPath[v] = min( MinOnPath[u] , Aug[u][v] );
                Q.push( v );
            }
        }
    }

    if ( u != N ) return false;

    int d = MinOnPath[u];
    while ( last[u] != 0 )
    {
        Aug[ last[u] ][ u ] -= d;
        Aug[ u ][ last[u] ] += d;
        u = last[u];
    }

    return true;
}

vector <int> T[MAXN];

void DFS( int v , vector <int>& V)
{
    been[v] = true;
    V.push_back( v );

    for ( int i = 0; i < p[v].size(); i++)
    {
        int u = p[v][i];
        if ( !been[u] ) DFS( u , V );
    }
}

int main()
{
    //freopen("input.in" , "r" , stdin);

    getPrimes();

    int N;
    cin >> N;

    int Even = 0, Odd = 0;
    for (int i = 2; i <= N + 1; i++)
    {
        cin >> a[i];

        if ( a[i] % 2 == 0)
        {
            G[1][i] = Aug[1][i] = 2;
            p[1].push_back( i );

            Even++;
        }
        else
        {
            G[i][N + 2] = Aug[i][N + 2] = 2;
            p[i].push_back( N + 2 );

            Odd++;
        }
    }

    if ( Odd != Even )
    {
        cout << "Impossible" << endl;
        return 0;
    }

    for (int i = 2; i <= N + 1; i++)
    {
        for (int j = i + 1; j <= N + 1; j++)
        {
            if ( lp[ a[i] + a[j] ] == a[i] + a[j] )
            {
                //cout << a[i] << " " << a[j] << endl;
                if ( a[i] % 2 == 0 )
                    G[i][j] = Aug[i][j] = 1;
                else
                    G[j][i] = Aug[j][i] = 1;

                p[i].push_back( j );
                p[j].push_back( i );
            }
        }
    }

    N += 2;
    while ( AugmentationSucceeded( N ) ) {};

    int flow = 0;
    for ( int i = 1; i <= N; i++)
        flow += Aug[i][1];

    if ( flow != 2 * Even )
    {
        cout << "Impossible" << endl;
        return 0;
    }

    for ( int i = 1; i <= N; i++)
    {
        p[i].clear();
        been[ i ] = false;
    }

    for ( int i = 2; i < N; i++)
    {
        for (int j = 2; j < N; j++)
        {
            if ( G[i][j] > 0 && Aug[i][j] == 0)
            {
                p[i - 1].push_back( j - 1 );
                p[j - 1].push_back( i - 1 );
                //cout << a[i] << " " << a[j] << endl;
            }
        }
    }

    int tables = 0;
    N -= 2;

    for ( int i = 1; i <= N; i++)
    {
        if ( !been[i] )
        {
            tables++;
            DFS( i , T[tables] );
        }
    }

    cout << tables << endl;

    for ( int i = 1; i <= tables; i++)
    {
        cout << T[i].size() << " ";
        for ( int j = 0; j < T[i].size(); j++)
            cout << T[i][j] << " ";
        cout << endl;
    }

    return 0;
}


#include <iostream>
#include <vector>
#include <utility>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <cstdio>
using namespace std;
const int MAXN = 205;
const int MAXP = 20006;
const int inf = 1000000007;

int lp[MAXP] = {0};
vector <int> primes;

void getPrimes()
{
    for ( int i = 2; i < MAXP; i++)
    {
        if ( lp[i] == 0 )
        {
            lp[i] = i;
            primes.push_back( i );
        }

        for ( int j = 0; j < primes.size() && primes[j] <= lp[i] && i * primes[j] < MAXP; j++)
            lp[ i * primes[j] ] = primes[j];
    }
}

int a[MAXN];
int G[MAXN][MAXN] = {0} , Aug[MAXN][MAXN] = {0};
vector <int> p[MAXN];

bool been[MAXN];
int last[MAXN] , MinOnPath[MAXN];
queue <int> Q;

bool AugmentationSucceeded( int N )
{
    for (int i = 1; i <= N; i++)
    {
        been[i] = false;
        last[i] = 0;
        MinOnPath[i] = inf;
    }

    while ( Q.size() != 0 ) Q.pop();

    been[1] = true;
    Q.push( 1 );

    int u;
    while ( Q.size() != 0 )
    {
        u = Q.front(); Q.pop();
        if ( u == N ) break;

        for ( int i = 0; i < p[u].size(); i++)
        {
            int v = p[u][i];
            if ( !been[v] && Aug[u][v] > 0 )
            {
                been[v] = true;
                last[v] = u;
                MinOnPath[v] = min( MinOnPath[u] , Aug[u][v] );
                Q.push( v );
            }
        }
    }

    if ( u != N ) return false;

    int d = MinOnPath[u];
    while ( last[u] != 0 )
    {
        Aug[ last[u] ][ u ] -= d;
        Aug[ u ][ last[u] ] += d;
        u = last[u];
    }

    return true;
}

vector <int> T[MAXN];

void DFS( int v , vector <int>& V)
{
    been[v] = true;
    V.push_back( v );

    for ( int i = 0; i < p[v].size(); i++)
    {
        int u = p[v][i];
        if ( !been[u] ) DFS( u , V );
    }
}

int main()
{
    //freopen("input.in" , "r" , stdin);

    getPrimes();

    int N;
    cin >> N;

    int Even = 0, Odd = 0;
    for (int i = 2; i <= N + 1; i++)
    {
        cin >> a[i];

        if ( a[i] % 2 == 0)
        {
            G[1][i] = Aug[1][i] = 2;
            p[1].push_back( i );

            Even++;
        }
        else
        {
            G[i][N + 2] = Aug[i][N + 2] = 2;
            p[i].push_back( N + 2 );

            Odd++;
        }
    }

    if ( Odd != Even )
    {
        cout << "Impossible" << endl;
        return 0;
    }

    for (int i = 2; i <= N + 1; i++)
    {
        for (int j = i + 1; j <= N + 1; j++)
        {
            if ( lp[ a[i] + a[j] ] == a[i] + a[j] )
            {
                //cout << a[i] << " " << a[j] << endl;
                if ( a[i] % 2 == 0 )
                {
                    G[i][j] = Aug[i][j] = 1;
                    p[i].push_back( j );
                }
                else
                {
                    G[j][i] = Aug[j][i] = 1;
                    p[j].push_back( i );
                }
            }
        }
    }

    N += 2;
    while ( AugmentationSucceeded( N ) ) {};

    for ( int i = 1; i <= N; i++)
    {
        p[i].clear();
        been[ i ] = false;
    }

    for ( int i = 2; i < N; i++)
    {
        for (int j = 2; j < N; j++)
        {
            if ( G[i][j] > 0 && Aug[i][j] == 0)
            {
                p[i - 1].push_back( j - 1 );
                p[j - 1].push_back( i - 1 );
            }
        }
    }

    int tables = 0;
    N -= 2;

    for ( int i = 1; i <= N; i++)
    {
        if ( !been[i] )
        {
            tables++;
            DFS( i , T[tables] );
        }
    }

    cout << tables << endl;

    for ( int i = 1; i <= tables; i++)
    {
        cout << T[i].size() << " ";
        for ( int j = 0; j < T[i].size(); j++)
            cout << T[i][j] << " ";
        cout << endl;
    }

    return 0;
}


#include <iostream>
#include <vector>
#include <utility>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <iomanip>
#include <cstdio>
using namespace std;
const int MAXN = 205;
const int MAXP = 20006;
const int inf = 1000000007;

int lp[MAXP] = {0};
vector <int> primes;

void getPrimes()
{
    for ( int i = 2; i < MAXP; i++)
    {
        if ( lp[i] == 0 )
        {
            lp[i] = i;
            primes.push_back( i );
        }

        for ( int j = 0; j < primes.size() && primes[j] <= lp[i] && i * primes[j] < MAXP; j++)
            lp[ i * primes[j] ] = primes[j];
    }
}

int a[MAXN];
int G[MAXN][MAXN] = {0} , Aug[MAXN][MAXN] = {0};
vector <int> p[MAXN];

bool been[MAXN];
int last[MAXN] , MinOnPath[MAXN];
queue <int> Q;

bool AugmentationSucceeded( int N )
{
    for (int i = 1; i <= N; i++)
    {
        been[i] = false;
        last[i] = 0;
        MinOnPath[i] = inf;
    }

    while ( Q.size() != 0 ) Q.pop();

    been[1] = true;
    Q.push( 1 );

    int u;
    while ( Q.size() != 0 )
    {
        u = Q.front(); Q.pop();
        if ( u == N ) break;

        for ( int i = 0; i < p[u].size(); i++)
        {
            int v = p[u][i];
            if ( !been[v] && Aug[u][v] > 0 )
            {
                been[v] = true;
                last[v] = u;
                MinOnPath[v] = min( MinOnPath[u] , Aug[u][v] );
                Q.push( v );
            }
        }
    }

    if ( u != N ) return false;

    int d = MinOnPath[u];
    while ( last[u] != 0 )
    {
        Aug[ last[u] ][ u ] -= d;
        Aug[ u ][ last[u] ] += d;
        u = last[u];
    }

    return true;
}

vector <int> T[MAXN];

void DFS( int v , vector <int>& V)
{
    been[v] = true;
    V.push_back( v );

    for ( int i = 0; i < p[v].size(); i++)
    {
        int u = p[v][i];
        if ( !been[u] ) DFS( u , V );
    }
}

int main()
{
    //freopen("input.in" , "r" , stdin);

    getPrimes();

    int N;
    cin >> N;

    int Even = 0, Odd = 0;
    for (int i = 2; i <= N + 1; i++)
    {
        cin >> a[i];

        if ( a[i] % 2 == 0)
        {
            G[1][i] = Aug[1][i] = 2;
            p[1].push_back( i );

            Even++;
        }
        else
        {
            G[i][N + 2] = Aug[i][N + 2] = 2;
            p[i].push_back( N + 2 );

            Odd++;
        }
    }

    if ( Odd != Even )
    {
        cout << "Impossible" << endl;
        return 0;
    }

    for (int i = 2; i <= N + 1; i++)
    {
        for (int j = i + 1; j <= N + 1; j++)
        {
            if ( lp[ a[i] + a[j] ] == a[i] + a[j] )
            {
                //cout << a[i] << " " << a[j] << endl;
                if ( a[i] % 2 == 0 )
                    G[i][j] = Aug[i][j] = 1;
                else
                    G[j][i] = Aug[j][i] = 1;

                p[i].push_back( j );
                p[j].push_back( i );
            }
        }
    }

    N += 2;
    while ( AugmentationSucceeded( N ) ) {};

    for ( int i = 1; i <= N; i++)
    {
        p[i].clear();
        been[ i ] = false;
    }

    for ( int i = 2; i < N; i++)
    {
        for (int j = 2; j < N; j++)
        {
            if ( G[i][j] > 0 && Aug[i][j] == 0)
            {
                p[i - 1].push_back( j - 1 );
                p[j - 1].push_back( i - 1 );
                //cout << a[i] << " " << a[j] << endl;
            }
        }
    }

    int tables = 0;
    N -= 2;

    for ( int i = 1; i <= N; i++)
    {
        if ( !been[i] )
        {
            tables++;
            DFS( i , T[tables] );
        }
    }

    cout << tables << endl;

    for ( int i = 1; i <= tables; i++)
    {
        cout << T[i].size() << " ";
        for ( int j = 0; j < T[i].size(); j++)
            cout << T[i][j] << " ";
        cout << endl;
    }

    return 0;
}


using namespace std;
#include<bits/stdc++.h>
#define debug(x) clog<<#x<<" = "<<x<<'\n'
#define ll long long
#define pll pair<ll,ll>
#define pii pair<int,int>
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
#define sz(c) ((int)c.size())
#define all(c) (c).begin(),(c).end()
#define MASK(i) (1LL<<(i))
#define BIT(x,i) (((x)>>(i))&1)
#define fn "510E"  /// ___FILE_NAME_HERE___
#define rep(c,it) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define __rep(c,it) for(__typeof((c).rbegin()) it=(c).rbegin();it!=(c).rend();it++)

template <class T,class U>
void maximize(T &x,U y)
{
    if(x < y)x=y;
}
template <class T,class U>
void minimize(T &x,U y)
{
    if(x > y)x=y;
}
template <class T>
T Abs(T x)
{
    return (x < 0 ? -x : x);
}
template <class T>
T safe_sqrt(T x)
{
    return sqrt(max(x,(T)0));
}
template <class T,class U,class V>
T addmod(T x,U k,V MOD)
{
    return ((x+k)%MOD + MOD)%MOD;
}
template <class T,class U,class V>
T submod(T x,U k,V MOD)
{
    return ((x-k)%MOD + MOD)%MOD;
}
template <class T,class U,class V>
T mul(T x,U y,V MOD)
{
    return (ll)x*y%MOD;
}
/*------------------------------------------END_OF_TEMPLATE------------------------------------------*/

namespace task{

const int N=3e2+2;
const int inf=1e7;
const int maxPrime=2e4+44;
bool isPrime[maxPrime];
int n,hasans=0,cntTable=0;
int a[N];
vector <int> table[N];
bool vis[N];

namespace dinic
{
    int f[N][N],cap[N][N],d[N];
    vector <int> adj[N];
    void addEdge(int u,int v,int w)
    {
        adj[u].pb(v),adj[v].pb(u);
        cap[u][v]+=w;
    }
    bool bfs()
    {
        memset(d,-1,sizeof(d));
        queue <int> q;
        q.push(0);
        d[0]=1;
        for(;sz(q);q.pop())
        {
            int u=q.front();
            if(u==n+1)return true;
            for(auto v : adj[u])
                if(d[v]==-1 and f[u][v] < cap[u][v])
                  d[v]=d[u]+1,q.push(v);
        }
        return false;
    }
    int dfs(int u,int minf)
    {
        if(!minf)return 0;
        if(u==n+1)return minf;
        for(auto v : adj[u])
        {
            if(d[v] != d[u] + 1)continue;
            int pushed=dfs(v,min(minf,cap[u][v] - f[u][v]));
            if(pushed)
            {
                f[u][v]+=pushed,f[v][u]-=pushed;
                return pushed;
            }
        }
        return 0;
    }
    int maxFlow()
    {
        int total=0;
        for(;;)
        {
            if(!bfs())break;
            for(int pushed=dfs(0,inf);pushed > 0;pushed=dfs(0,inf))
                total+=pushed;
        }
        return total;
    }
}

void sieve()
{
    memset(isPrime,true,sizeof(isPrime));
    isPrime[0]=isPrime[1]=false;
    for(int i=2;i*i<=maxPrime;++i)
        if(isPrime[i])
          for(int j=i<<1;j<=maxPrime;j+=i)
            isPrime[j]=false;
}

void dfs(int u,int val)
{
    table[cntTable].pb(u);
    vis[u]=true;
    for(auto v : dinic::adj[u])
    {
        if(vis[v] or v==0 or v==n+1)continue;
        if(dinic::f[u][v] != val)continue;
        dfs(v,-val);// bipartite graph.
    }
}

void solve()
{
    sieve();
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",a+i),hasans+=(a[i]&1);
    if(hasans != (n>>1))puts("Impossible"),exit(0);
    for(int i=1;i<=n;++i)
      if(a[i] & 1)dinic::addEdge(0,i,2); else dinic::addEdge(i,n+1,2);
    for(int i=1;i<=n;++i)
      if(a[i] & 1)
        for(int j=1;j<=n;++j)
           if((a[j]&1)^1)
              if(isPrime[a[i] + a[j]])dinic::addEdge(i,j,1);
    int flow=dinic::maxFlow();
    if(flow != (hasans<<1))puts("Impossible"),exit(0);
    for(int i=1;i<=n;++i)
        if(!vis[i] and (a[i] & 1))
          ++cntTable,dfs(i,1);
    printf("%d\n",cntTable);
    for(int i=1;i<=cntTable;++i,printf("\n"))
    {
         printf("%d ",sz(table[i]));
         for(auto res : table[i])
           printf("%d ",res);
    }
}}

int main(void)
{
    #ifndef ONLINE_JUDGE
    freopen(fn".inp","r",stdin);
    freopen(fn".out","w",stdout);
    #endif // ONLINE_JUDGE
    task::solve();
}


using namespace std;
#include<bits/stdc++.h>
#define debug(x) clog<<#x<<" = "<<x<<'\n'
#define ll long long
#define pll pair<ll,ll>
#define pii pair<int,int>
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
#define sz(c) ((int)c.size())
#define all(c) (c).begin(),(c).end()
#define MASK(i) (1LL<<(i))
#define BIT(x,i) (((x)>>(i))&1)
#define fn "510E"  /// ___FILE_NAME_HERE___
#define rep(c,it) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++)
#define __rep(c,it) for(__typeof((c).rbegin()) it=(c).rbegin();it!=(c).rend();it++)

template <class T,class U>
void maximize(T &x,U y)
{
    if(x < y)x=y;
}
template <class T,class U>
void minimize(T &x,U y)
{
    if(x > y)x=y;
}
template <class T>
T Abs(T x)
{
    return (x < 0 ? -x : x);
}
template <class T>
T safe_sqrt(T x)
{
    return sqrt(max(x,(T)0));
}
template <class T,class U,class V>
T addmod(T x,U k,V MOD)
{
    return ((x+k)%MOD + MOD)%MOD;
}
template <class T,class U,class V>
T submod(T x,U k,V MOD)
{
    return ((x-k)%MOD + MOD)%MOD;
}
template <class T,class U,class V>
T mul(T x,U y,V MOD)
{
    return (ll)x*y%MOD;
}
/*------------------------------------------END_OF_TEMPLATE------------------------------------------*/

namespace task{

const int N=3e2+2;
const int inf=1e7;
const int maxPrime=2e4+44;
bool isPrime[maxPrime];
int n,odd=0,cntTable=0;
int a[N];
vector <int> table[N];
bool vis[N];

namespace dinic
{
    int f[N][N],cap[N][N],d[N];
    vector <int> adj[N];
    void addEdge(int u,int v,int w)
    {
        adj[u].pb(v),adj[v].pb(u);
        cap[u][v]+=w;
    }
    bool bfs()
    {
        memset(d,-1,sizeof(d));
        queue <int> q;
        q.push(0);
        d[0]=1;
        for(;sz(q);q.pop())
        {
            int u=q.front();
            if(u==n+1)return true;
            for(auto v : adj[u])
                if(d[v]==-1 and f[u][v] < cap[u][v])
                  d[v]=d[u]+1,q.push(v);
        }
        return false;
    }
    int dfs(int u,int minf)
    {
        if(!minf)return 0;
        if(u==n+1)return minf;
        for(auto v : adj[u])
        {
            if(d[v] != d[u] + 1)continue;
            int pushed=dfs(v,min(minf,cap[u][v] - f[u][v]));
            if(pushed)
            {
                f[u][v]+=pushed,f[v][u]-=pushed;
                return pushed;
            }
        }
        return 0;
    }
    int maxFlow()
    {
        int total=0;
        for(;;)
        {
            if(!bfs())break;
            for(int pushed=dfs(0,inf);pushed > 0;pushed=dfs(0,inf))
                total+=pushed;
        }
        return total;
    }
}

void sieve()
{
    memset(isPrime,true,sizeof(isPrime));
    isPrime[0]=isPrime[1]=false;
    for(int i=2;i*i<=maxPrime;++i)
        if(isPrime[i])
          for(int j=i<<1;j<=maxPrime;j+=i)
            isPrime[j]=false;
}

void dfs(int u,int val)
{
    table[cntTable].pb(u);
    vis[u]=true;
    for(auto v : dinic::adj[u])
    {
        if(vis[v] or v==0 or v==n+1)continue;
        if(dinic::f[u][v] != val)continue;
        dfs(v,-val);// bipartite graph.
    }
}

void solve()
{
    sieve();
    scanf("%d",&n);
    for(int i=1;i<=n;++i)scanf("%d",a+i),odd+=(a[i]&1);
    if(odd<<1 != n)puts("Impossible"),exit(0);
    for(int i=1;i<=n;++i)
      if(a[i] & 1)dinic::addEdge(0,i,2); else dinic::addEdge(i,n+1,2);
    for(int i=1;i<=n;++i)
      if(a[i] & 1)
        for(int j=1;j<=n;++j)
           if((a[j]&1)^1)
              if(isPrime[a[i] + a[j]])dinic::addEdge(i,j,1);
    int flow=dinic::maxFlow();
    if(flow != (odd<<1))puts("Impossible"),exit(0);
    for(int i=1;i<=n;++i)
        if(!vis[i] and (a[i] & 1))
          ++cntTable,dfs(i,1);
    printf("%d\n",cntTable);
    for(int i=1;i<=cntTable;++i,printf("\n"))
    {
         printf("%d ",sz(table[i]));
         for(auto res : table[i])
           printf("%d ",res);
    }
}}

int main(void)
{
    #ifndef ONLINE_JUDGE
    freopen(fn".inp","r",stdin);
    freopen(fn".out","w",stdout);
    #endif // ONLINE_JUDGE
    task::solve();
}


#include <bits/stdc++.h>

#define pb push_back
#define mp make_pair
#define sz(x) (int)(x).size()
#define li long long
#define ld long double
#define x first
#define y second
#define pt pair<int, int>
#define pll pair<li, li>
#define forn(i, t) for(int i = 0; i < (t); i++)
#define fore(i, f, t) for(int i = (f); i < (t); i++)
#define forr(i, f, t) for(int i = (f) - 1; i >= (t); i--)
#define all(x) (x).begin(), (x).end()
#define ins insert

using namespace std;

const int INF = 1e9;
const int MOD = 1e9 + 7;
const li INF64 = 2e18;
const ld EPS = 1e-7;

mt19937 myrand(time(NULL));

const int N = 200 + 7;
const int M = 100000 + 7;
const int MAXN = 20000 + 13;

struct edge{
	int v, u;
	int cap, flow;

	edge(){};
	edge(int v, int u, int cap, int flow) : v(v), u(u), cap(cap), flow(flow) {};
};

int n;
int rn;
vector<int> g[N], h[N];
int lst;
edge e[M];
int a[N];
int s, t;

int rem(int it){
	return e[it].cap - e[it].flow;
}

void add_edge(int v, int u, int cap){
	g[v].pb(lst);
	e[lst++] = edge(v, u, cap, 0);
	g[u].pb(lst);
	e[lst++] = edge(u, v, 0, 0);
}

bool read(){
	if (scanf("%d", &rn) != 1)
		return 0;
	forn(i, rn)
		scanf("%d", &a[i]);

	lst = 0;
	s = rn, t = s + 1;
	n = t + 1;

	forn(i, n){
		g[i].clear();
		h[i].clear();
	}

	return 1;
}

int d[N];

bool bfs(int s, int t){
	static int q[N];
	int l = 0, r = 0;

	forn(i, n)
		d[i] = -1;

	d[s] = 0;
	q[r++] = s;

	while (l != r && d[t] == -1){
		int v = q[l++];

		for (auto it : g[v])
			if (d[e[it].u] == -1 && rem(it) != 0){
				d[e[it].u] = d[e[it].v] + 1;
				q[r++] = e[it].u;
			}
	}

	return (d[t] != -1);
}

int last[N];

int dfs(int v, int t, int mx){
	if (mx == 0 || v == t)
		return mx;
	int sum = 0;

	for (; last[v] < sz(g[v]); ++last[v]){
		int it = g[v][last[v]];
		int u = e[it].u;

		if (d[u] != d[v] + 1)
			continue;

		int flow = dfs(u, t, min(mx, rem(it)));

		if (flow){
			sum += flow;
			mx -= flow;
			e[it].flow += flow;
			e[it ^ 1].flow -= flow;
		}
	}

	return sum;
}

int Dinic(){
	int ans = 0;

	while (true){
		if (!bfs(s, t))
			break;

		forn(i, n)
			last[i] = 0;

		int add;

		while (add = dfs(s, t, INF))
			ans += add;
	}

	return ans;
}

int prime[MAXN];

void sieve(){
	forn(i, MAXN)
		prime[i] = 1;

	for (int i = 2; i < MAXN; ++i){
		if (!prime[i])
			continue;
		for (int j = i * i; j < MAXN; j += i)
			prime[j] = 0;
	}
}

int used[N];
vector<int> cyc[N];
int k;

void dfs0(int v){
	used[v] = 1;
	cyc[k].pb(v + 1);

	for (auto u : h[v])
		if (!used[u])
			dfs0(u);
}

void solve(){
	sieve();

	forn(i, rn)
		forn(j, rn)
			if (a[i] % 2 == 0 && prime[a[i] + a[j]])
				add_edge(i, j, 1);

	forn(i, rn)
		if (a[i] % 2 == 0)
			add_edge(s, i, 2);
		else
			add_edge(i, t, 2);

	int ans = Dinic();
	//printf("%d\n", ans);

	if (ans != rn){
		printf("Impossible\n");
		return;
	}

	memset(used, 0, sizeof(used));

	for (int i = 0; i < lst - 2 * rn; i += 2)
		if (e[i].flow){
			int x = e[i].v, y = e[i].u;
			//printf("[%d %d] ", a[x].x, a[y].x);
			h[x].pb(y);
			h[y].pb(x);
		}

	//printf("\n");

	memset(used, 0, sizeof(used));
	forn(i, rn)
		cyc[i].clear();

	k = 0;
	forn(i, rn){
		if (!used[i]){
			dfs0(i);
			if (sz(cyc[k]) <= 2){
				printf("Impossible\n");
				return;
			}
			++k;
		}
	}

	printf("%d\n", k);
	forn(i, k){
		printf("%d ", sz(cyc[i]));
		for (auto it : cyc[i])
			printf("%d ", it);
		printf("\n");
	}
}

int main(){
	#ifdef _DEBUG
		freopen("input.txt", "r", stdin);
	#endif
	while (read())
		solve();
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
struct edge
{
    int to, nxt, cost;
    edge(int to = 0, int nxt = -1, int cost = 0) : to(to), nxt(nxt), cost(cost) {}
} e[200001];
int n, a[201], not_prime[100001], E, head[100001], dep[100001], cur[100001], s, t;
vector<int> odd, even, cir;
bool vis[201];
void add(int f, int t, int c)
{
    e[E].to = t;
    e[E].cost = c;
    e[E].nxt = head[f];
    head[f] = E++;
}
void init()
{
    not_prime[1] = 1;
    for (int i = 2; i * i <= 100000; i++)
    {
        if (not_prime[i])
        {
            continue;
        }
        for (int j = i * i; j <= 100000; j += i)
        {
            not_prime[j] = 1;
        }
    }
}
bool bfs()
{
    queue<int> q;
    memset(dep, 0, sizeof(dep));
    for (int i = 0; i <= n + 1; i++)
    {
        cur[i] = head[i];
    }
    q.push(s);
    dep[s] = 1;
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i = head[u]; i != -1; i = e[i].nxt)
        {
            int v = e[i].to;
            if (e[i].cost && !dep[v])
            {
                dep[v] = dep[u] + 1;
                q.push(v);
            }
        }
    }
    return dep[t];
}
int dfs(int u, int sum)
{
    if (u == t || !sum)
    {
        return sum;
    }
    int ans = 0;
    for (int i = cur[u]; i != -1; i = e[i].nxt)
    {
        int v = e[i].to;
        if (dep[v] == dep[u] + 1 && e[i].cost)
        {
            int minn = dfs(v, min(sum, e[i].cost));
            if (minn)
            {
                e[i].cost -= minn;
                e[i ^ 1].cost += minn;
                ans += minn;
                sum -= minn;
                if (!sum)
                {
                    break;
                }
            }
        }
        cur[u] = e[i].nxt;
    }
    if (!ans)
    {
        dep[u] = -1;
    }
    return ans;
}
int dinic()
{
    int ans = 0;
    while (bfs())
    {
        ans += dfs(s, 2e9);
    }
    return ans;
}
void getcir(int u)
{
    cir.push_back(u);
    vis[u] = 1;
    for (int i = head[u]; i != -1; i = e[i].nxt)
    {
        int v = e[i].to;
        if (vis[v] || !e[i ^ (a[u] & 1)].cost)
        {
            continue;
        }
        getcir(v);
    }
}
int main(int argc, char const *argv[])
{
    init();
    memset(head, -1, sizeof(head));
    scanf("%d", &n);
    s = 0;
    t = n + 1;
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        if (a[i] & 1)
        {
            odd.push_back(i);
            add(s, i, 2);
            add(i, s, 0);
        }
        else
        {
            even.push_back(i);
            add(i, t, 2);
            add(t, i, 0);
        }
    }
    if (odd.size() != even.size())
    {
        printf("Impossible");
        return 0;
    }
    for (auto i : odd)
    {
        for (auto j : even)
        {
            if (!not_prime[a[i] + a[j]])
            {
                add(i, j, 1);
                add(j, i, 0);
            }
        }
    }
    if (dinic() != n)
    {
        printf("Impossible");
        return 0;
    }
    for (int i = 1; i <= n; i++)
    {
        if (vis[i])
        {
            continue;
        }
        cir.clear();
        getcir(i);
        printf("%d ", (int)cir.size());
        for (auto j : cir)
        {
            printf("%d ", j);
        }
        printf("\n");
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
struct edge
{
    int to, nxt, cost;
    edge(int to = 0, int nxt = -1, int cost = 0) : to(to), nxt(nxt), cost(cost) {}
} e[200001];
int n, a[201], not_prime[100001], E, head[100001], dep[100001], cur[100001], s, t;
vector<int> odd, even, cir;
vector<vector<int> > Ans;
bool vis[201];
void add(int f, int t, int c)
{
    e[E].to = t;
    e[E].cost = c;
    e[E].nxt = head[f];
    head[f] = E++;
}
void init()
{
    not_prime[1] = 1;
    for (int i = 2; i * i <= 100000; i++)
    {
        if (not_prime[i])
        {
            continue;
        }
        for (int j = i * i; j <= 100000; j += i)
        {
            not_prime[j] = 1;
        }
    }
}
bool bfs()
{
    queue<int> q;
    memset(dep, 0, sizeof(dep));
    for (int i = 0; i <= n + 1; i++)
    {
        cur[i] = head[i];
    }
    q.push(s);
    dep[s] = 1;
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i = head[u]; i != -1; i = e[i].nxt)
        {
            int v = e[i].to;
            if (e[i].cost && !dep[v])
            {
                dep[v] = dep[u] + 1;
                q.push(v);
            }
        }
    }
    return dep[t];
}
int dfs(int u, int sum)
{
    if (u == t || !sum)
    {
        return sum;
    }
    int ans = 0;
    for (int i = cur[u]; i != -1; i = e[i].nxt)
    {
        int v = e[i].to;
        if (dep[v] == dep[u] + 1 && e[i].cost)
        {
            int minn = dfs(v, min(sum, e[i].cost));
            if (minn)
            {
                e[i].cost -= minn;
                e[i ^ 1].cost += minn;
                ans += minn;
                sum -= minn;
                if (!sum)
                {
                    break;
                }
            }
        }
        cur[u] = e[i].nxt;
    }
    if (!ans)
    {
        dep[u] = -1;
    }
    return ans;
}
int dinic()
{
    int ans = 0;
    while (bfs())
    {
        ans += dfs(s, 2e9);
    }
    return ans;
}
void getcir(int u)
{
    cir.push_back(u);
    vis[u] = 1;
    for (int i = head[u]; i != -1; i = e[i].nxt)
    {
        int v = e[i].to;
        if (vis[v] || !e[i ^ (a[u] & 1)].cost)
        {
            continue;
        }
        getcir(v);
    }
}
int main(int argc, char const *argv[])
{
    init();
    memset(head, -1, sizeof(head));
    scanf("%d", &n);
    s = 0;
    t = n + 1;
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        if (a[i] & 1)
        {
            odd.push_back(i);
            add(s, i, 2);
            add(i, s, 0);
        }
        else
        {
            even.push_back(i);
            add(i, t, 2);
            add(t, i, 0);
        }
    }
    if (odd.size() != even.size())
    {
        printf("Impossible");
        return 0;
    }
    for (auto i : odd)
    {
        for (auto j : even)
        {
            if (!not_prime[a[i] + a[j]])
            {
                add(i, j, 1);
                add(j, i, 0);
            }
        }
    }
    if (dinic() != n)
    {
        printf("Impossible");
        return 0;
    }
    for (int i = 1; i <= n; i++)
    {
        if (vis[i])
        {
            continue;
        }
        cir.clear();
        getcir(i);
        Ans.push_back(cir);
    }
    printf("%d\n", (int)Ans.size());
    for (auto i : Ans)
    {
        printf("%d ", (int)i.size());
        for (auto j : i)
        {
            printf("%d ", j);
        }
        printf("\n");
    }
    return 0;
}


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

inline int gi()
{
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	int sum = 0;
	while('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
	return sum;
}

const int maxn = 205, maxa = 20005, Inf = 1 << 30;

int n, s, t, ans, a[maxn], isprm[maxa];

void pre()
{
	static bool vis[maxa];
	static int p[maxa], pcnt;
	for (int i = 2; i < maxa; ++i) {
		if (!vis[i]) p[++pcnt] = i, isprm[i] = 1;
		for (int j = 1; j <= pcnt && p[j] * i < maxa; ++j) {
			vis[p[j] * i] = 1;
			if (i % p[j] == 0) break;
		}
	}
}

struct edge
{
	int to, next, cap;
} e[maxn * maxn << 1];
int h[maxn], cur[maxn], tot = 1, vis[maxn], dis[maxn];
queue<int> que;

inline void add(int u, int v, int w)
{
	/*if (u == s) printf("s ");
	else printf("%d ", u);
	if (v == t) printf("t %d\n", w);
	else printf("%d %d\n", v, w);*/
	e[++tot] = (edge) {v, h[u], w}; h[u] = tot;
	e[++tot] = (edge) {u, h[v], 0}; h[v] = tot;
}

bool bfs()
{
	dis[s] = 0; vis[s] = 1; que.push(s);
	static int u;
	while (!que.empty()) {
		u = que.front(); que.pop();
		for (int i = h[u], v; v = e[i].to, i; i = e[i].next)
			if (!vis[v] && e[i].cap) {
				vis[v] = 1; dis[v] = dis[u] + 1;
				que.push(v);
			}
	}
	return vis[t];
}

int dfs(int u, int a)
{
	if (u == t || !a) return a;
	int f, flow = 0;
	for (int &i = cur[u], v; v = e[i].to, i; i = e[i].next)
		if (dis[v] == dis[u] + 1 && (f = dfs(v, min(e[i].cap, a)))) {
			e[i].cap -= f; e[i ^ 1].cap += f;
			flow += f; a -= f;
			if (!a) break;
		}
	return flow;
}

int max_flow()
{
	int res = 0;
	while (bfs()) {
		memset(vis + 1, 0, sizeof(int) * t);
		memcpy(cur + 1, h + 1, sizeof(int) * t);
		res += dfs(s, Inf);
	}
	return res;
}

int m;
vector<int> to[maxn], vec[maxn];

void dfs(int u)
{
	vec[m].push_back(u);
	vis[u] = 1;
	for (int v : to[u])
		if (!vis[v]) dfs(v);
}

int main()
{
	n = gi();
	for (int i = 1; i <= n; ++i) a[i] = gi();

	pre();

	s = n + 1; t = s + 1;
	for (int i = 1; i <= n; ++i)
		if (a[i] & 1) add(s, i, 2), ans += 2;
		else add(i, t, 2);
	if (ans != n) return puts("Impossible"), 0;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			if (isprm[a[i] + a[j]]) add(i, j, 1);

	if (ans != max_flow()) return puts("Impossible"), 0;

	for (int u = 1; u <= n; ++u)
		for (int i = h[u], v; v = e[i].to, i; i = e[i].next)
			if (!e[i].cap && v <= n) to[u].push_back(v), to[v].push_back(u);

	memset(vis + 1, 0, sizeof(int) * t);
	for (int i = 1; i <= n; ++i)
		if (!vis[i]) ++m, dfs(i);

	printf("%d\n", m);
	for (int i = 1; i <= m; ++i) {
		printf("%lu ", vec[i].size());
		for (int u : vec[i]) printf("%d ", u);
		puts("");
	}

	return 0;
}


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

inline int gi()
{
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	int sum = 0;
	while('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
	return sum;
}

const int maxn = 205, maxa = 20005, Inf = 1 << 30;

int n, s, t, ans, a[maxn], isprm[maxa];

void pre()
{
	static bool vis[maxa];
	static int p[maxa], pcnt;
	for (int i = 2; i < maxa; ++i) {
		if (!vis[i]) p[++pcnt] = i, isprm[i] = 1;
		for (int j = 1; j <= pcnt && p[j] * i < maxa; ++j) {
			vis[p[j] * i] = 1;
			if (i % p[j] == 0) break;
		}
	}
}

struct edge
{
	int to, next, cap;
} e[maxn * maxn << 1];
int h[maxn], cur[maxn], tot = 1, vis[maxn], dis[maxn];
queue<int> que;

inline void add(int u, int v, int w)
{
	/*if (u == s) printf("s ");
	else printf("%d ", u);
	if (v == t) printf("t %d\n", w);
	else printf("%d %d\n", v, w);*/
	e[++tot] = (edge) {v, h[u], w}; h[u] = tot;
	e[++tot] = (edge) {u, h[v], 0}; h[v] = tot;
}

bool bfs()
{
	dis[s] = 0; vis[s] = 1; que.push(s);
	static int u;
	while (!que.empty()) {
		u = que.front(); que.pop();
		for (int i = h[u], v; v = e[i].to, i; i = e[i].next)
			if (!vis[v] && e[i].cap) {
				vis[v] = 1; dis[v] = dis[u] + 1;
				que.push(v);
			}
	}
	return vis[t];
}

int dfs(int u, int a)
{
	if (u == t || !a) return a;
	int f, flow = 0;
	for (int &i = cur[u], v; v = e[i].to, i; i = e[i].next)
		if (dis[v] == dis[u] + 1 && (f = dfs(v, min(e[i].cap, a)))) {
			e[i].cap -= f; e[i ^ 1].cap += f;
			flow += f; a -= f;
			if (!a) break;
		}
	return flow;
}

int max_flow()
{
	int res = 0;
	while (bfs()) {
		memset(vis + 1, 0, sizeof(int) * t);
		memcpy(cur + 1, h + 1, sizeof(int) * t);
		res += dfs(s, Inf);
	}
	return res;
}

int m;
vector<int> to[maxn], vec[maxn];

void dfs(int u)
{
	vec[m].push_back(u);
	vis[u] = 1;
	for (int v : to[u])
		if (!vis[v]) dfs(v);
}

int main()
{
	n = gi();
	for (int i = 1; i <= n; ++i) a[i] = gi();

	pre();

	s = n + 1; t = s + 1;
	for (int i = 1; i <= n; ++i)
		if (a[i] & 1) add(s, i, 2), ans += 2;
		else add(i, t, 2);
	if (ans != n) return puts("Impossible"), 0;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= n; ++j)
			if (isprm[a[i] + a[j]]) add(i, j, 1);

	if (ans != max_flow()) return puts("Impossible"), 0;

	for (int u = 1; u <= n; ++u)
		if (a[u] & 1)
			for (int i = h[u], v; v = e[i].to, i; i = e[i].next)
				if (!e[i].cap && v <= n) to[u].push_back(v), to[v].push_back(u);

	memset(vis + 1, 0, sizeof(int) * t);
	for (int i = 1; i <= n; ++i)
		if (!vis[i]) ++m, dfs(i);

	printf("%d\n", m);
	for (int i = 1; i <= m; ++i) {
		printf("%lu ", vec[i].size());
		for (int u : vec[i]) printf("%d ", u);
		puts("");
	}

	return 0;
}


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

inline int gi()
{
	char c = getchar();
	while(c < '0' || c > '9') c = getchar();
	int sum = 0;
	while('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
	return sum;
}

const int maxn = 205, maxa = 20005, Inf = 1 << 30;

int n, s, t, ans, a[maxn], isprm[maxa];

void pre()
{
	static bool vis[maxa];
	static int p[maxa], pcnt;
	for (int i = 2; i < maxa; ++i) {
		if (!vis[i]) p[++pcnt] = i, isprm[i] = 1;
		for (int j = 1; j <= pcnt && p[j] * i < maxa; ++j) {
			vis[p[j] * i] = 1;
			if (i % p[j] == 0) break;
		}
	}
}

struct edge
{
	int to, next, cap;
} e[maxn * maxn << 1];
int h[maxn], cur[maxn], tot = 1, vis[maxn], dis[maxn];
queue<int> que;

inline void add(int u, int v, int w)
{
	/*if (u == s) printf("s ");
	else printf("%d ", u);
	if (v == t) printf("t %d\n", w);
	else printf("%d %d\n", v, w);*/
	e[++tot] = (edge) {v, h[u], w}; h[u] = tot;
	e[++tot] = (edge) {u, h[v], 0}; h[v] = tot;
}

bool bfs()
{
	dis[s] = 0; vis[s] = 1; que.push(s);
	static int u;
	while (!que.empty()) {
		u = que.front(); que.pop();
		for (int i = h[u], v; v = e[i].to, i; i = e[i].next)
			if (!vis[v] && e[i].cap) {
				vis[v] = 1; dis[v] = dis[u] + 1;
				que.push(v);
			}
	}
	return vis[t];
}

int dfs(int u, int a)
{
	if (u == t || !a) return a;
	int f, flow = 0;
	for (int &i = cur[u], v; v = e[i].to, i; i = e[i].next)
		if (dis[v] == dis[u] + 1 && (f = dfs(v, min(e[i].cap, a)))) {
			e[i].cap -= f; e[i ^ 1].cap += f;
			flow += f; a -= f;
			if (!a) break;
		}
	return flow;
}

int max_flow()
{
	int res = 0;
	while (bfs()) {
		memset(vis + 1, 0, sizeof(int) * t);
		memcpy(cur + 1, h + 1, sizeof(int) * t);
		res += dfs(s, Inf);
	}
	return res;
}

int m;
vector<int> to[maxn], vec[maxn];

void dfs(int u)
{
	vec[m].push_back(u);
	vis[u] = 1;
	for (int v : to[u])
		if (!vis[v]) dfs(v);
}

int main()
{
	n = gi();
	for (int i = 1; i <= n; ++i) a[i] = gi();

	pre();

	s = n + 1; t = s + 1;
	for (int i = 1; i <= n; ++i)
		if (a[i] & 1) add(s, i, 2), ans += 2;
		else add(i, t, 2);
	if (ans != n) return puts("Impossible"), 0;
	for (int i = 1; i <= n; ++i)
		if (a[i] & 1)
			for (int j = 1; j <= n; ++j)
				if (isprm[a[i] + a[j]]) add(i, j, 1);

	if (ans != max_flow()) return puts("Impossible"), 0;

	for (int u = 1; u <= n; ++u)
		if (a[u] & 1)
			for (int i = h[u], v; v = e[i].to, i; i = e[i].next)
				if (!e[i].cap && v <= n) to[u].push_back(v), to[v].push_back(u);

	memset(vis + 1, 0, sizeof(int) * t);
	for (int i = 1; i <= n; ++i)
		if (!vis[i]) ++m, dfs(i);

	printf("%d\n", m);
	for (int i = 1; i <= m; ++i) {
		printf("%lu ", vec[i].size());
		for (int u : vec[i]) printf("%d ", u);
		puts("");
	}

	return 0;
}


#include<bits/stdc++.h>
#define fi first
#define se second
#define io ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define ll long long

using namespace std;

const int MAXN = 207;

struct edge
{
	int flow = 0, cap, from, to;
	edge (int fl, int c, int fr, int t)
	{
		flow = fl, cap = c, from = fr, to = t;
	}
};

int n, a[MAXN], s, t, tr[MAXN], res = 0;
vector<edge> e;
vector<int> adj[MAXN], nxt[MAXN], ans[MAXN];
bitset<MAXN> vis;

void dfs(int u)
{
	vis[u] = 1, ans[res].push_back(u);
	for (auto v: nxt[u])
		if (!vis[v]) dfs(v);
}

void input()
{
//	freopen("test.INP","r",stdin);
	io;
	cin >> n;
	for (int i = 1; i <= n; ++i) cin >> a[i];
}

void add_edge(int u, int v, int cap)
{
	adj[u].push_back((int)e.size());
	e.push_back(edge(0, cap, u, v));
	adj[v].push_back((int)e.size());
	e.push_back(edge(0, 0, v, u));
}

bool is_prime(int n)
{
	for (int i = 2; i <= sqrt(n); ++i)
		if (n % i == 0) return 0;
	return 1;
}

bool found_path()
{
	for (int i = 1; i <= t; ++i) tr[i] = -1;
	tr[s] = 0;
	queue<int> q;
	q.push(s);
	while (q.size())
	{
		int u = q.front();
		q.pop();
		for (auto it: adj[u])
		{
			int v = e[it].to;
			if (tr[v] == -1 && e[it].cap > e[it].flow)
			{
				tr[v] = it;
				if (v == t) return 1;
				q.push(v);
			}
		}
	}
	return 0;
}

void solve()
{
	s = n + 1, t = s + 1;
	for (int i = 1; i <= n; ++i)
	{
		if (a[i] & 1) add_edge(s, i, 2); else add_edge(i, t, 2);
		for (int j = 1; j <= n; ++j)
			if (is_prime(a[i] + a[j])) add_edge(i, j, 1);
	}

	int maxflow = 0;
	while (found_path())
	{
		int delta = 3;
		for (int u = t; u != s; u = e[tr[u]].from)
			delta = min(delta, e[tr[u]].cap - e[tr[u]].flow);
		for (int u = t; u != s; u = e[tr[u]].from)
		{
			e[tr[u]].flow += delta;
			e[tr[u] ^ 1].flow -= delta;
		}
		maxflow += delta;
	}

	if (maxflow != n) cout << "Impossible"; else
	{
		for (auto it: e)
			if (it.cap == 1 && it.flow == 1)
			{
				nxt[it.from].push_back(it.to);
				nxt[it.to].push_back(it.from);
			}

		for (int i = 1; i <= n; ++i)
			if (!vis[i]) ++res, dfs(i);

		cout << res << '\n';
		for (int i = 1; i <= res; ++i, cout << '\n')
		{
			cout << (int)ans[i].size() << ' ';
			for (auto v: ans[i]) cout << v << ' ';
		}
	}
}

int main()
{
	input();
	solve();
}


#include<bits/stdc++.h>
#define fi first
#define se second
#define io ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define ll long long

using namespace std;

const int MAXN = 207;

struct edge
{
	int flow = 0, cap, from, to;
	edge (int fl, int c, int fr, int t)
	{
		flow = fl, cap = c, from = fr, to = t;
	}
};

int n, a[MAXN], s, t, tr[MAXN], res = 0;
vector<edge> e;
vector<int> adj[MAXN], nxt[MAXN], ans[MAXN];
bitset<MAXN> vis;

void dfs(int u)
{
	vis[u] = 1, ans[res].push_back(u);
	for (auto v: nxt[u])
		if (!vis[v]) dfs(v);
}

void input()
{
//	freopen("test.INP","r",stdin);
	io;
	cin >> n;
	for (int i = 1; i <= n; ++i) cin >> a[i];
}

void add_edge(int u, int v, int cap)
{
	adj[u].push_back((int)e.size());
	e.push_back(edge(0, cap, u, v));
	adj[v].push_back((int)e.size());
	e.push_back(edge(0, 0, v, u));
}

bool is_prime(int n)
{
	for (int i = 2; i <= sqrt(n); ++i)
		if (n % i == 0) return 0;
	return 1;
}

bool found_path()
{
	for (int i = 1; i <= t; ++i) tr[i] = -1;
	tr[s] = 0;
	queue<int> q;
	q.push(s);
	while (q.size())
	{
		int u = q.front();
		q.pop();
		for (auto it: adj[u])
		{
			int v = e[it].to;
			if (tr[v] == -1 && e[it].cap > e[it].flow)
			{
				tr[v] = it;
				if (v == t) return 1;
				q.push(v);
			}
		}
	}
	return 0;
}

void solve()
{
	s = n + 1, t = s + 1;
	for (int i = 1; i <= n; ++i)
	{
		if (a[i] & 1) add_edge(s, i, 2); else add_edge(i, t, 2);
		for (int j = 1; j <= n; ++j)
			if (is_prime(a[i] + a[j]) && (a[i] & 1))
				add_edge(i, j, 1);
	}

	int maxflow = 0;
	while (found_path())
	{
		int delta = 3;
		for (int u = t; u != s; u = e[tr[u]].from)
			delta = min(delta, e[tr[u]].cap - e[tr[u]].flow);
		for (int u = t; u != s; u = e[tr[u]].from)
		{
			e[tr[u]].flow += delta;
			e[tr[u] ^ 1].flow -= delta;
		}
		maxflow += delta;
	}

	if (maxflow != n) cout << "Impossible"; else
	{
		for (auto it: e)
			if (it.cap == 1 && it.flow == 1)
			{
				nxt[it.from].push_back(it.to);
				nxt[it.to].push_back(it.from);
//				cout << a[it.from] << ' ' << a[it.to] << '\n';
			}

		for (int i = 1; i <= n; ++i)
			if (!vis[i]) ++res, dfs(i);

		cout << res << '\n';
		for (int i = 1; i <= res; ++i, cout << '\n')
		{
			cout << (int)ans[i].size() << ' ';
			for (auto v: ans[i]) cout << v << ' ';
		}
	}
}

int main()
{
	input();
	solve();
}


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

const int N = 205;
vector<int> ans[N];
vector<int> v[N];
int vis[N];
int ptr = 0;

struct FlowEdge {
    int v, u;
    long long cap, flow = 0;
    FlowEdge(int v, int u, long long cap) : v(v), u(u), cap(cap) {}
};

struct Dinic {
    const long long flow_inf = 1e18;
    vector<FlowEdge> edges;
    vector<vector<int>> adj;
    int n, m = 0;
    int s, t;
    vector<int> level, ptr;
    queue<int> q;

    Dinic(int n, int s, int t) : n(n), s(s), t(t) {
        adj.resize(n);
        level.resize(n);
        ptr.resize(n);
    }

    void add_edge(int v, int u, long long cap) {
        edges.emplace_back(v, u, cap);
        edges.emplace_back(u, v, 0);
        adj[v].push_back(m);
        adj[u].push_back(m + 1);
        m += 2;
    }

    bool bfs() {
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (int id : adj[v]) {
                if (edges[id].cap - edges[id].flow < 1)
                    continue;
                if (level[edges[id].u] != -1)
                    continue;
                level[edges[id].u] = level[v] + 1;
                q.push(edges[id].u);
            }
        }
        return level[t] != -1;
    }

    long long dfs(int v, long long pushed) {
        if (pushed == 0)
            return 0;
        if (v == t)
            return pushed;
        for (int& cid = ptr[v]; cid < (int)adj[v].size(); cid++) {
            int id = adj[v][cid];
            int u = edges[id].u;
            if (level[v] + 1 != level[u] || edges[id].cap - edges[id].flow < 1)
                continue;
            long long tr = dfs(u, min(pushed, edges[id].cap - edges[id].flow));
            if (tr == 0)
                continue;
            edges[id].flow += tr;
            edges[id ^ 1].flow -= tr;
            return tr;
        }
        return 0;
    }

    long long flow() {
        long long f = 0;
        while (true) {
            fill(level.begin(), level.end(), -1);
            level[s] = 0;
            q.push(s);
            if (!bfs())
                break;
            fill(ptr.begin(), ptr.end(), 0);
            while (long long pushed = dfs(s, flow_inf)) {
                f += pushed;
            }
        }
        return f;
    }
};

void dfs(int x) {

    if(vis[x])
        return;
    vis[x] = 1;
    ans[ptr].push_back(x);

    for(auto it : v[x])
        dfs(it);
}

bool prime(int a) {

    for(int i=2; i*i <= a; i++)
        if(a % i == 0)
            return 0;

    return 1;
}

int main() {

    int s = 201, t = 202;
	Dinic d(N, s, t);
    int cnt[2] = {0, 0};

    int n;
    int a[N];

    cin >> n;
    for(int i=0; i<n; i++)
        cin >> a[i];

    for(int i=0; i<n; i++) {
        for(int j=0; j<n; j++)
            if(a[i]%2 == 1 && a[j]%2 == 0 && prime(a[i] + a[j]))
                d.add_edge(i, j, 1);

        if(a[i] % 2 == 1)
            d.add_edge(s, i, 2);
        else
            d.add_edge(i, t, 2);
        cnt[a[i] % 2]++;
    }

    if(cnt[0] != cnt[1] || d.flow() != 2*cnt[0]) {
        printf("Impossible\n");
        return 0;
    }

    for(auto it : d.edges)
        if(it.flow > 0) {
            if(it.v == s || it.u == t)
                continue;

            // printf(">> %d %d\n", it.u, it.v);
            v[it.u].push_back(it.v);
            v[it.v].push_back(it.u);
        }

    memset(vis, 0, sizeof(vis));
    for(int i=0; i<n; i++)
        if(!vis[i]) {
            dfs(i);
            ptr++;
        }

    printf("%d\n", ptr);
    for(int i=0; i<ptr; i++) {
        printf("%d ", (int)ans[i].size());
        for(auto it : ans[i])
            printf("%d ", it);

        printf("\n");
    }
}


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

const int N = 205;
vector<int> ans[N];
vector<int> v[N];
int vis[N];
int ptr = 0;

struct FlowEdge {
    int v, u;
    long long cap, flow = 0;
    FlowEdge(int v, int u, long long cap) : v(v), u(u), cap(cap) {}
};

struct Dinic {
    const long long flow_inf = 1e18;
    vector<FlowEdge> edges;
    vector<vector<int>> adj;
    int n, m = 0;
    int s, t;
    vector<int> level, ptr;
    queue<int> q;

    Dinic(int n, int s, int t) : n(n), s(s), t(t) {
        adj.resize(n);
        level.resize(n);
        ptr.resize(n);
    }

    void add_edge(int v, int u, long long cap) {
        edges.emplace_back(v, u, cap);
        edges.emplace_back(u, v, 0);
        adj[v].push_back(m);
        adj[u].push_back(m + 1);
        m += 2;
    }

    bool bfs() {
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (int id : adj[v]) {
                if (edges[id].cap - edges[id].flow < 1)
                    continue;
                if (level[edges[id].u] != -1)
                    continue;
                level[edges[id].u] = level[v] + 1;
                q.push(edges[id].u);
            }
        }
        return level[t] != -1;
    }

    long long dfs(int v, long long pushed) {
        if (pushed == 0)
            return 0;
        if (v == t)
            return pushed;
        for (int& cid = ptr[v]; cid < (int)adj[v].size(); cid++) {
            int id = adj[v][cid];
            int u = edges[id].u;
            if (level[v] + 1 != level[u] || edges[id].cap - edges[id].flow < 1)
                continue;
            long long tr = dfs(u, min(pushed, edges[id].cap - edges[id].flow));
            if (tr == 0)
                continue;
            edges[id].flow += tr;
            edges[id ^ 1].flow -= tr;
            return tr;
        }
        return 0;
    }

    long long flow() {
        long long f = 0;
        while (true) {
            fill(level.begin(), level.end(), -1);
            level[s] = 0;
            q.push(s);
            if (!bfs())
                break;
            fill(ptr.begin(), ptr.end(), 0);
            while (long long pushed = dfs(s, flow_inf)) {
                f += pushed;
            }
        }
        return f;
    }
};

void dfs(int x) {

    if(vis[x])
        return;
    vis[x] = 1;
    ans[ptr].push_back(x);

    for(auto it : v[x])
        dfs(it);
}

bool prime(int a) {

    for(int i=2; i*i <= a; i++)
        if(a % i == 0)
            return 0;

    return 1;
}

int main() {

    int s = 201, t = 202;
	Dinic d(N, s, t);
    int cnt[2] = {0, 0};

    int n;
    int a[N];

    cin >> n;
    for(int i=0; i<n; i++)
        cin >> a[i];

    for(int i=0; i<n; i++) {
        for(int j=0; j<n; j++)
            if(a[i]%2 == 1 && a[j]%2 == 0 && prime(a[i] + a[j]))
                d.add_edge(i, j, 1);

        if(a[i] % 2 == 1)
            d.add_edge(s, i, 2);
        else
            d.add_edge(i, t, 2);
        cnt[a[i] % 2]++;
    }

    if(cnt[0] != cnt[1] || d.flow() != 2*cnt[0]) {
        printf("Impossible\n");
        return 0;
    }

    for(auto it : d.edges)
        if(it.flow > 0) {
            if(it.v == s || it.u == t)
                continue;

            // printf(">> %d %d\n", it.u, it.v);
            v[it.u].push_back(it.v);
            v[it.v].push_back(it.u);
        }

    memset(vis, 0, sizeof(vis));
    for(int i=0; i<n; i++)
        if(!vis[i]) {
            dfs(i);
            ptr++;
        }

    printf("%d\n", ptr);
    for(int i=0; i<ptr; i++) {
        printf("%d ", (int)ans[i].size());
        for(auto it : ans[i])
            printf("%d ", it + 1);

        printf("\n");
    }
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <string>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1000000007;

const int INF = 0x3FFFFFFF;
struct Dinic {
    struct edge {
        int t, c, r;
        edge(int _t, int _c, int _r) : t(_t), c(_c), r(_r) {}
    };
    vector<int> l, nxt;
    vector<vector<edge>> e;
    Dinic(int n) : e(n + 1) {}
    void add_edge(int u, int v, int w) {//directed
        e[u].push_back(edge(v, w, (int)e[v].size()));
        e[v].push_back(edge(u, 0, (int)e[u].size() - 1));
    }
    edge& rev(const edge& E) {
        return e[E.t][E.r];
    }
    bool bfs(int s, int t) {
        l.assign(e.size(), INF);
        l[s] = 1;
        queue<int> Q;
        for (Q.push(s); !Q.empty(); Q.pop()) {
            s = Q.front();
            for (const edge& E : e[s])
                if (E.c > 0 && l[E.t] > l[s] + 1) {
                    l[E.t] = l[s] + 1; Q.push(E.t);
                }
        }
        return l[t] < INF;
    }
    int dfs(int s, int t, int num = INF) {
        if (s == t || num == 0) return num;
        int ans = 0;
        for (int& i = nxt[s]; num && i < e[s].size(); i += num > 0) {
            edge& E = e[s][i];
            if (E.c > 0 && l[s] + 1 == l[E.t]) {
                int tmp = dfs(E.t, t, min(num, E.c));
                rev(E).c += tmp, ans += tmp;
                E.c -= tmp, num -= tmp;
            }
        }
        return ans > 0 ? ans : l[s] = 0;
    }
    int operator()(int s, int t) {
        int ans = 0;
        for (; bfs(s, t); ans += dfs(s, t)) nxt.assign(e.size(), 0);
        return ans;
    }
};

int main() {
    ios::sync_with_stdio(false);
    int n, a[213] = {};
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    Dinic D(n + 2);
    for (int i = 1; i <= n; i++) {
        if (a[i] % 2) D.add_edge(i, n + 1, 2);
        else D.add_edge(0, i, 2);
    }
    for (int i = 1; i <= n; i++) if (a[i] % 2 == 0) {
        for (int j = 1; j <= n; j++) if (a[j] % 2) {
            bool y = 0;
            for (int k = 2; k * k <= a[i] + a[j]; k++) {
                if ((a[i] + a[j]) % k == 0) y = 1;
            }
            if (!y) D.add_edge(i, j, 1);
        }
    }
    if (D(0, n + 1) != n) {
        cout << "Impossible\n";
        return 0;
    }
    vector<int> g[213] = {};
    vector<vector<int>> z;
    bool b[213] = {};
    for (int i = 1; i <= n; i++) if (a[i] % 2 == 0) {
        for (auto j : D.e[i]) if (j.t >= 1 && j.t <= n && !j.c) {
            g[i].push_back(j.t);
            g[j.t].push_back(i);
        }
    }
    for (int i = 1; i <= n; i++) if (!b[i]) {
        z.push_back({i});
        int c = g[i][0];
        b[i] = 1;
        while (1) {
            b[c] = 1;
            z.back().push_back(c);
            if (!b[g[c][0]]) {
                c = g[c][0];
            } else if (!b[g[c][1]]) {
                c = g[c][1];
            } else break;
        }
    }
    cout << z.size() << '\n';
    for (auto i : z) {
        cout << i.size() << ' ';
        for (int j : i) cout << j << ' ';
        cout << '\n';
    }
}


/*
ID: kfoozminus
TASK:
LANG: C++
*/

#include <bits/stdc++.h>
using namespace std;
//typedefs
/*
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
typedef pair <int, pii> piii;
typedef vector <int> vi;
typedef vector <ll> vl;
typedef pair <ll, ll> pll;
const double PI = acos(-1);
*/
//typedefs
#define ll long long
#define ull unsigned long long
#define pii pair <int, int>
#define piii pair <int, pii>
#define vi vector <int>
#define vl vector <ll>
#define pll pair <ll, ll>
#define PI acos(-1)
//defines
#define MP make_pair
#define PB push_back
#define F first
#define S second
#define mem(a, b) memset(a, b, sizeof(a))
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) (a*(b/gcd(a,b)))
#define SQR(a) ((a)*(a))
#define inf 100000000
#define mod 1000000007
#define mod1 1000000007
#define mod2 1000000009
#define b1 43
#define b2 41
#define EPS 1e-9
//define harmonic(n) 0.57721566490153286l+log(n)
#define nl puts("")
#define odd(n) ((n)&1)
#define even(n) (!((n)&1))
#define vsort(v) sort(v.begin(), v.end())
#define lc (node<<1)
#define rc ((node<<1)|1)
#define ran(a, b) ((((rand() << 15) ^ rand()) % ((b) - (a) + 1)) + (a))
//loop
#define rep(i, n) for(int i = 0; i < n; ++i)
#define REP(i, n) for(int i = 1; i <= n; ++i)
//input
#define si(a) scanf("%d", &a)
#define sii(a, b) scanf("%d%d", &a, &b)
#define siii(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define sl(a) scanf("%lld", &a)
#define sll(a, b) scanf("%lld%lld", &a, &b)
#define slll(a, b, c) scanf("%lld%lld%lld", &a, &b, &c)
#define sd(a) scanf("%lf", &a)
#define sc(a) scanf("%c", &a)
#define sst(a) scanf("%s", a)
inline bool EQ(double a, double b) { return fabs(a-b) < 1e-9; }
//debug
#ifdef kfoozminus

template < typename F, typename S >
ostream& operator << ( ostream& os, const pair< F, S > & p ) {
	return os << "(" << p.first << ", " << p.second << ")";
}

template < typename T >
ostream &operator << ( ostream & os, const vector< T > &v ) {
	os << "{";
	for(auto it = v.begin(); it != v.end(); ++it) {
		if( it != v.begin() ) os << ", ";
		os << *it;
	}
    return os << "}";
}

template < typename T >
ostream &operator << ( ostream & os, const set< T > &v ) {
	os << "[";
	for(auto it = v.begin(); it != v.end(); ++it) {
		if( it != v.begin()) os << ", ";
		os << *it;
	}
    return os << "]";
}

template < typename F, typename S >
ostream &operator << ( ostream & os, const map< F, S > &v ) {
	os << "[";
	for(auto it = v.begin(); it != v.end(); ++it) {
		if( it != v.begin() ) os << ", ";
		os << it -> first << " = " << it -> second ;
	}
    return os << "]";
}

#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0)

clock_t tStart = clock();
#define timeStamp dbg("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC)

void faltu () { cerr << endl; }

template <typename T>
void faltu( T a[], int n ) {
	for(int i = 0; i < n; ++i) cerr << a[i] << ' ';
	cerr << endl;
}

template <typename T, typename ... hello>
void faltu( T arg, const hello &... rest) { cerr << arg << ' '; faltu(rest...); }

#else
#define dbg(args...)
#endif
/*
ll add(ll a, ll b) {
	ll ret = a+b;
	if(ret >= mod) ret -= mod;
	return ret;
}

ll subtract(ll a, ll b) {
	ll ret = a-b;
	if(ret < 0) ret += mod;
	return ret;
}

ll mult(ll a, ll b) {
	ll ret = a*b;
	if(ret >= mod) ret %= mod;
	return ret;
}

ll bigmod(ll a, ll b) {
	ll ret = 1;
	while(b) {
		if(b&1) ret = mult(ret, a);
		b >>= 1; a = mult(a, a);
	}
	return ret;
}
*/

//ll inverse(ll n) { return bigmod(n, mod-2); }

#define PMX 1000000

int marked[PMX/64 + 2];
vi primes;

#define mark(x) marked[x >> 6] |= (1 << ((x & 63) >> 1))
#define check(x) (marked[x >> 6] & (1 << ((x & 63) >> 1)))

bool isPrime(int x)
{
	return (x > 1) && ((x == 2) || ((x & 1) && (!(check(x)))));
}

void seive(int n)
{
	int i, j;
	for(i = 3; i * i <= n; i += 2) if(!check(i)) for(j = i * i; j <= n; j += i << 1) mark(j);
	primes.PB(2);
	for(i = 3; i <= n; i += 2) if(isPrime(i)) primes.PB(i);
}

//Direction Array
//int fx[]={1, -1, 0, 0}; int fy[]={0, 0, 1, -1};
//int fx[]={0, 0, 1, -1, -1, 1, -1, 1}; int fy[]={-1, 1, 0, 0, 1, 1, -1, -1};

//bit manipulation
/*
bool checkBit(int n, int i) { return (n&(1<<i)); }
int setBit(int n, int i) { return (n|(1<<i)); }
int resetBit(int n, int i) { return (n&(~(1<<i))); }
*/
//end of template

#define MX 100007
#define MXN 407
#define MXE 200007

int source, sink, NN, n, m;
int Q[MXN], fin[MXN], pro[MXN], dist[MXN], nEdge;
int flow[MXE], cap[MXE], nex[MXE], to[MXE];

void init()
{
	//src = _src, snk = _snk, nNode = _n, nEdge = 0;
	for(int i = 0; i <= NN; i ++) fin[i] = -1;
	nEdge = 0;
}

void addEdge(int u, int v, int c)
{
	to[ nEdge ] = v; cap[ nEdge ] = c; flow[ nEdge ] = 0; nex[ nEdge ] = fin[ u ]; fin[ u ] = nEdge ++;
	to[ nEdge ] = u; cap[ nEdge ] = 0; flow[ nEdge ] = 0; nex[ nEdge ] = fin[ v ]; fin[ v ] = nEdge ++;
}

bool bfs()
{ int st, en;

	for(int i = 0; i <= NN; i ++) dist[i] = -1;

	dist[source] = st = en = 0;

	Q[ en ++ ] = source;

	while(st < en) {

		int u = Q[ st ++ ];

		for(int i = fin[u]; i >= 0; i = nex[ i ]) {

			int v = to[ i ];
			if(flow[i] < cap[i] && dist[v] == -1) {

				dist[v] = dist[u] + 1;
				Q[ en ++ ] = v;
			}
		}
	}

	return dist[sink] != -1;
}

int dfs(int u, int fl)
{
	if(u == sink) return fl;

	for(int &i = pro[ u ]; i >= 0; i = nex[ i ]) {

		int v = to[ i ];

		if(flow[i] < cap[i] && dist[v] == dist[u] + 1) {

			int df = dfs(v, min(cap[ i ] - flow[ i ], fl) );

			if(df > 0) {

				flow[i] += df;
				flow[i ^ 1] -= df;

				return df;
			}
		}
	}
	return 0;
}

int dinic()
{
	int ret = 0;

	for(int i = 0; i < nEdge; i ++) flow[i] = 0;

	while( bfs() ) {

		for(int i = 0; i <= NN; i ++) pro[i] = fin[i];

		while(true) {

			int df = dfs(source, inf);
			if(df) ret += df;
			else break;
		}
	}
	return ret;
}

int a[MX];
vector<int> ans[MX];
int vis[MX], ed[300][300];

int main () {
#ifdef kfoozminus
//	freopen("in", "r", stdin);
//	freopen("out", "w", stdout);
#endif
	seive(200000);
	int odd = 0, even = 0, i, j;

	scanf("%d", &n);
	for(i = 0; i < n; i ++) {
		scanf("%d", &a[i]);
		if(a[i] & 1) odd ++;
		else even ++;
	}
	if(odd != even) {
		printf("Impossible\n");
		return 0;
	}

	source = 0;
	sink = n + 1;
	NN = sink;
	init();
	for(i = 0; i < n; i ++) {
		if(a[i] & 1) {
			addEdge(source, i + 1, 2);
		}
		else addEdge(i + 1, sink, 2);
		if(a[i] & 1) {
			for(j = 0; j < n; j ++) {
				if(isPrime(a[i] + a[j])) {
					addEdge(i + 1, j + 1, 1);
					//dbg(a[i] + a[j]);
				}
			}
		}
	}
	int p = dinic();
	dbg(p);
	int in = -1;
	if(p == 2 * even) {
		//printf("Possible\n");
		for(i = 1; i <= n; i ++) {
			//while(true) {
				for(j = fin[i]; j >= 0; j = nex[j]) {
					if(cap[j] == 2) continue;
					if(cap[j] == 1 && flow[j] == 1) {
						ed[i][ to[j] ] = 1;
						ed[ to[j] ][i] = 1;
						//dbg(i, to[j]);
						//i = to[j];
						//break;
					}
				}
			//}
		}
		for(int k = 1; k <= n; k ++) {
			i = k;
			if(vis[i] == 0) in ++;
			while(vis[i] == 0) {
				vis[i] = 1;
				ans[in].PB(i);
				for(j = 1; j <= n; j ++) {
					if(vis[j]) continue;
					if(ed[i][j]) {
						i = j;
						break;
					}
				}
			}
		}
		for(i = 1; i <= n; i ++) dbg(i, vis[i]);
		printf("%d\n", in + 1);
		for(i = 0; i <= in; i ++) {
			printf("%d ", ans[i].size());
			for(auto it : ans[i]) printf("%d ", it);
			nl;
		}
	}
	else printf("Impossible\n");

//	timeStamp;
	return 0;
}


/*
ID: kfoozminus
TASK:
LANG: C++
*/

#include <bits/stdc++.h>
using namespace std;
//typedefs
/*
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
typedef pair <int, pii> piii;
typedef vector <int> vi;
typedef vector <ll> vl;
typedef pair <ll, ll> pll;
const double PI = acos(-1);
*/
//typedefs
#define ll long long
#define ull unsigned long long
#define pii pair <int, int>
#define piii pair <int, pii>
#define vi vector <int>
#define vl vector <ll>
#define pll pair <ll, ll>
#define PI acos(-1)
//defines
#define MP make_pair
#define PB push_back
#define F first
#define S second
#define mem(a, b) memset(a, b, sizeof(a))
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) (a*(b/gcd(a,b)))
#define SQR(a) ((a)*(a))
#define inf 100000000
#define mod 1000000007
#define mod1 1000000007
#define mod2 1000000009
#define b1 43
#define b2 41
#define EPS 1e-9
//define harmonic(n) 0.57721566490153286l+log(n)
#define nl puts("")
#define odd(n) ((n)&1)
#define even(n) (!((n)&1))
#define vsort(v) sort(v.begin(), v.end())
#define lc (node<<1)
#define rc ((node<<1)|1)
#define ran(a, b) ((((rand() << 15) ^ rand()) % ((b) - (a) + 1)) + (a))
//loop
#define rep(i, n) for(int i = 0; i < n; ++i)
#define REP(i, n) for(int i = 1; i <= n; ++i)
//input
#define si(a) scanf("%d", &a)
#define sii(a, b) scanf("%d%d", &a, &b)
#define siii(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define sl(a) scanf("%lld", &a)
#define sll(a, b) scanf("%lld%lld", &a, &b)
#define slll(a, b, c) scanf("%lld%lld%lld", &a, &b, &c)
#define sd(a) scanf("%lf", &a)
#define sc(a) scanf("%c", &a)
#define sst(a) scanf("%s", a)
inline bool EQ(double a, double b) { return fabs(a-b) < 1e-9; }
//debug
#ifdef kfoozminus

template < typename F, typename S >
ostream& operator << ( ostream& os, const pair< F, S > & p ) {
	return os << "(" << p.first << ", " << p.second << ")";
}

template < typename T >
ostream &operator << ( ostream & os, const vector< T > &v ) {
	os << "{";
	for(auto it = v.begin(); it != v.end(); ++it) {
		if( it != v.begin() ) os << ", ";
		os << *it;
	}
    return os << "}";
}

template < typename T >
ostream &operator << ( ostream & os, const set< T > &v ) {
	os << "[";
	for(auto it = v.begin(); it != v.end(); ++it) {
		if( it != v.begin()) os << ", ";
		os << *it;
	}
    return os << "]";
}

template < typename F, typename S >
ostream &operator << ( ostream & os, const map< F, S > &v ) {
	os << "[";
	for(auto it = v.begin(); it != v.end(); ++it) {
		if( it != v.begin() ) os << ", ";
		os << it -> first << " = " << it -> second ;
	}
    return os << "]";
}

#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0)

clock_t tStart = clock();
#define timeStamp dbg("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC)

void faltu () { cerr << endl; }

template <typename T>
void faltu( T a[], int n ) {
	for(int i = 0; i < n; ++i) cerr << a[i] << ' ';
	cerr << endl;
}

template <typename T, typename ... hello>
void faltu( T arg, const hello &... rest) { cerr << arg << ' '; faltu(rest...); }

#else
#define dbg(args...)
#endif
/*
ll add(ll a, ll b) {
	ll ret = a+b;
	if(ret >= mod) ret -= mod;
	return ret;
}

ll subtract(ll a, ll b) {
	ll ret = a-b;
	if(ret < 0) ret += mod;
	return ret;
}

ll mult(ll a, ll b) {
	ll ret = a*b;
	if(ret >= mod) ret %= mod;
	return ret;
}

ll bigmod(ll a, ll b) {
	ll ret = 1;
	while(b) {
		if(b&1) ret = mult(ret, a);
		b >>= 1; a = mult(a, a);
	}
	return ret;
}
*/

//ll inverse(ll n) { return bigmod(n, mod-2); }

#define PMX 1000000

int marked[PMX/64 + 2];
vi primes;

#define mark(x) marked[x >> 6] |= (1 << ((x & 63) >> 1))
#define check(x) (marked[x >> 6] & (1 << ((x & 63) >> 1)))

bool isPrime(int x)
{
	return (x > 1) && ((x == 2) || ((x & 1) && (!(check(x)))));
}

void seive(int n)
{
	int i, j;
	for(i = 3; i * i <= n; i += 2) if(!check(i)) for(j = i * i; j <= n; j += i << 1) mark(j);
	primes.PB(2);
	for(i = 3; i <= n; i += 2) if(isPrime(i)) primes.PB(i);
}

//Direction Array
//int fx[]={1, -1, 0, 0}; int fy[]={0, 0, 1, -1};
//int fx[]={0, 0, 1, -1, -1, 1, -1, 1}; int fy[]={-1, 1, 0, 0, 1, 1, -1, -1};

//bit manipulation
/*
bool checkBit(int n, int i) { return (n&(1<<i)); }
int setBit(int n, int i) { return (n|(1<<i)); }
int resetBit(int n, int i) { return (n&(~(1<<i))); }
*/
//end of template

#define MX 100007
#define MXN 207
#define MXE 100007

int source, sink, NN, n, m;
int Q[MXN], fin[MXN], pro[MXN], dist[MXN], nEdge;
int flow[MXE], cap[MXE], nex[MXE], to[MXE];

void init()
{
	//src = _src, snk = _snk, nNode = _n, nEdge = 0;
	for(int i = 0; i <= NN; i ++) fin[i] = -1;
	nEdge = 0;
}

void addEdge(int u, int v, int c)
{
	to[ nEdge ] = v; cap[ nEdge ] = c; flow[ nEdge ] = 0; nex[ nEdge ] = fin[ u ]; fin[ u ] = nEdge ++;
	to[ nEdge ] = u; cap[ nEdge ] = 0; flow[ nEdge ] = 0; nex[ nEdge ] = fin[ v ]; fin[ v ] = nEdge ++;
}

bool bfs()
{ int st, en;

	for(int i = 0; i <= NN; i ++) dist[i] = -1;

	dist[source] = st = en = 0;

	Q[ en ++ ] = source;

	while(st < en) {

		int u = Q[ st ++ ];

		for(int i = fin[u]; i >= 0; i = nex[ i ]) {

			int v = to[ i ];
			if(flow[i] < cap[i] && dist[v] == -1) {

				dist[v] = dist[u] + 1;
				Q[ en ++ ] = v;
			}
		}
	}

	return dist[sink] != -1;
}

int dfs(int u, int fl)
{
	if(u == sink) return fl;

	for(int &i = pro[ u ]; i >= 0; i = nex[ i ]) {

		int v = to[ i ];

		if(flow[i] < cap[i] && dist[v] == dist[u] + 1) {

			int df = dfs(v, min(cap[ i ] - flow[ i ], fl) );

			if(df > 0) {

				flow[i] += df;
				flow[i ^ 1] -= df;

				return df;
			}
		}
	}
	return 0;
}

int dinic()
{
	int ret = 0;

	for(int i = 0; i < nEdge; i ++) flow[i] = 0;

	while( bfs() ) {

		for(int i = 0; i <= NN; i ++) pro[i] = fin[i];

		while(true) {

			int df = dfs(source, inf);
			if(df) ret += df;
			else break;
		}
	}
	return ret;
}

int a[MX];
vector<int> ans[MX];
int vis[MX], ed[300][300];

int main () {
#ifdef kfoozminus
//	freopen("in", "r", stdin);
//	freopen("out", "w", stdout);
#endif
	seive(100000);
	int odd = 0, even = 0, i, j;

	scanf("%d", &n);
	for(i = 0; i < n; i ++) {
		scanf("%d", &a[i]);
		if(a[i] & 1) odd ++;
		else even ++;
	}
	if(odd != even) {
		printf("Impossible\n");
		return 0;
	}

	source = 0;
	sink = n + 1;
	NN = sink;
	init();
	for(i = 0; i < n; i ++) {
		if(a[i] & 1) {
			addEdge(source, i + 1, 2);
		}
		else addEdge(i + 1, sink, 2);
		if(a[i] & 1) {
			for(j = 0; j < n; j ++) {
				if(isPrime(a[i] + a[j])) {
					addEdge(i + 1, j + 1, 1);
					//dbg(a[i] + a[j]);
				}
			}
		}
	}
	int p = dinic();
	dbg(p);
	int in = -1;
	if(p == 2 * even) {
		//printf("Possible\n");
		for(i = 1; i <= n; i ++) {
			//while(true) {
				for(j = fin[i]; j >= 0; j = nex[j]) {
					if(cap[j] == 2) continue;
					if(flow[j] == 1) {
						ed[i][ to[j] ] = 1;
						ed[ to[j] ][i] = 1;
						dbg(i, to[j]);
						//i = to[j];
						//break;
					}
				}
			//}
		}
		for(i = 1; i <= n; i ++) {
			if(vis[i] == 0) in ++;
			while(vis[i] == 0) {
				vis[i] = 1;
				ans[in].PB(i);
				for(j = 1; j <= n; j ++) {
					if(vis[j]) continue;
					if(ed[i][j]) {
						i = j;
						break;
					}
				}
			}
		}
		printf("%d\n", in + 1);
		for(i = 0; i <= in; i ++) {
			printf("%d ", ans[i].size());
			for(auto it : ans[i]) printf("%d ", it);
			nl;
		}
	}
	else printf("Impossible\n");

//	timeStamp;
	return 0;
}


/*
ID: kfoozminus
TASK:
LANG: C++
*/

#include <bits/stdc++.h>
using namespace std;
//typedefs
/*
typedef long long ll;
typedef unsigned long long ull;
typedef pair <int, int> pii;
typedef pair <int, pii> piii;
typedef vector <int> vi;
typedef vector <ll> vl;
typedef pair <ll, ll> pll;
const double PI = acos(-1);
*/
//typedefs
#define ll long long
#define ull unsigned long long
#define pii pair <int, int>
#define piii pair <int, pii>
#define vi vector <int>
#define vl vector <ll>
#define pll pair <ll, ll>
#define PI acos(-1)
//defines
#define MP make_pair
#define PB push_back
#define F first
#define S second
#define mem(a, b) memset(a, b, sizeof(a))
#define gcd(a,b) __gcd(a,b)
#define lcm(a,b) (a*(b/gcd(a,b)))
#define SQR(a) ((a)*(a))
#define inf 100000000
#define mod 1000000007
#define mod1 1000000007
#define mod2 1000000009
#define b1 43
#define b2 41
#define EPS 1e-9
//define harmonic(n) 0.57721566490153286l+log(n)
#define nl puts("")
#define odd(n) ((n)&1)
#define even(n) (!((n)&1))
#define vsort(v) sort(v.begin(), v.end())
#define lc (node<<1)
#define rc ((node<<1)|1)
#define ran(a, b) ((((rand() << 15) ^ rand()) % ((b) - (a) + 1)) + (a))
//loop
#define rep(i, n) for(int i = 0; i < n; ++i)
#define REP(i, n) for(int i = 1; i <= n; ++i)
//input
#define si(a) scanf("%d", &a)
#define sii(a, b) scanf("%d%d", &a, &b)
#define siii(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define sl(a) scanf("%lld", &a)
#define sll(a, b) scanf("%lld%lld", &a, &b)
#define slll(a, b, c) scanf("%lld%lld%lld", &a, &b, &c)
#define sd(a) scanf("%lf", &a)
#define sc(a) scanf("%c", &a)
#define sst(a) scanf("%s", a)
inline bool EQ(double a, double b) { return fabs(a-b) < 1e-9; }
//debug
#ifdef kfoozminus

template < typename F, typename S >
ostream& operator << ( ostream& os, const pair< F, S > & p ) {
	return os << "(" << p.first << ", " << p.second << ")";
}

template < typename T >
ostream &operator << ( ostream & os, const vector< T > &v ) {
	os << "{";
	for(auto it = v.begin(); it != v.end(); ++it) {
		if( it != v.begin() ) os << ", ";
		os << *it;
	}
    return os << "}";
}

template < typename T >
ostream &operator << ( ostream & os, const set< T > &v ) {
	os << "[";
	for(auto it = v.begin(); it != v.end(); ++it) {
		if( it != v.begin()) os << ", ";
		os << *it;
	}
    return os << "]";
}

template < typename F, typename S >
ostream &operator << ( ostream & os, const map< F, S > &v ) {
	os << "[";
	for(auto it = v.begin(); it != v.end(); ++it) {
		if( it != v.begin() ) os << ", ";
		os << it -> first << " = " << it -> second ;
	}
    return os << "]";
}

#define dbg(args...) do {cerr << #args << " : "; faltu(args); } while(0)

clock_t tStart = clock();
#define timeStamp dbg("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC)

void faltu () { cerr << endl; }

template <typename T>
void faltu( T a[], int n ) {
	for(int i = 0; i < n; ++i) cerr << a[i] << ' ';
	cerr << endl;
}

template <typename T, typename ... hello>
void faltu( T arg, const hello &... rest) { cerr << arg << ' '; faltu(rest...); }

#else
#define dbg(args...)
#endif
/*
ll add(ll a, ll b) {
	ll ret = a+b;
	if(ret >= mod) ret -= mod;
	return ret;
}

ll subtract(ll a, ll b) {
	ll ret = a-b;
	if(ret < 0) ret += mod;
	return ret;
}

ll mult(ll a, ll b) {
	ll ret = a*b;
	if(ret >= mod) ret %= mod;
	return ret;
}

ll bigmod(ll a, ll b) {
	ll ret = 1;
	while(b) {
		if(b&1) ret = mult(ret, a);
		b >>= 1; a = mult(a, a);
	}
	return ret;
}
*/

//ll inverse(ll n) { return bigmod(n, mod-2); }

#define PMX 1000000

int marked[PMX/64 + 2];
vi primes;

#define mark(x) marked[x >> 6] |= (1 << ((x & 63) >> 1))
#define check(x) (marked[x >> 6] & (1 << ((x & 63) >> 1)))

bool isPrime(int x)
{
	return (x > 1) && ((x == 2) || ((x & 1) && (!(check(x)))));
}

void seive(int n)
{
	int i, j;
	for(i = 3; i * i <= n; i += 2) if(!check(i)) for(j = i * i; j <= n; j += i << 1) mark(j);
	primes.PB(2);
	for(i = 3; i <= n; i += 2) if(isPrime(i)) primes.PB(i);
}

//Direction Array
//int fx[]={1, -1, 0, 0}; int fy[]={0, 0, 1, -1};
//int fx[]={0, 0, 1, -1, -1, 1, -1, 1}; int fy[]={-1, 1, 0, 0, 1, 1, -1, -1};

//bit manipulation
/*
bool checkBit(int n, int i) { return (n&(1<<i)); }
int setBit(int n, int i) { return (n|(1<<i)); }
int resetBit(int n, int i) { return (n&(~(1<<i))); }
*/
//end of template

#define MX 100007
#define MXN 207
#define MXE 100007

int source, sink, NN, n, m;
int Q[MXN], fin[MXN], pro[MXN], dist[MXN], nEdge;
int flow[MXE], cap[MXE], nex[MXE], to[MXE];

void init()
{
	//src = _src, snk = _snk, nNode = _n, nEdge = 0;
	for(int i = 0; i <= NN; i ++) fin[i] = -1;
	nEdge = 0;
}

void addEdge(int u, int v, int c)
{
	to[ nEdge ] = v; cap[ nEdge ] = c; flow[ nEdge ] = 0; nex[ nEdge ] = fin[ u ]; fin[ u ] = nEdge ++;
	to[ nEdge ] = u; cap[ nEdge ] = c; flow[ nEdge ] = 0; nex[ nEdge ] = fin[ v ]; fin[ v ] = nEdge ++;
}

bool bfs()
{ int st, en;

	for(int i = 0; i <= NN; i ++) dist[i] = -1;

	dist[source] = st = en = 0;

	Q[ en ++ ] = source;

	while(st < en) {

		int u = Q[ st ++ ];

		for(int i = fin[u]; i >= 0; i = nex[ i ]) {

			int v = to[ i ];
			if(flow[i] < cap[i] && dist[v] == -1) {

				dist[v] = dist[u] + 1;
				Q[ en ++ ] = v;
			}
		}
	}

	return dist[sink] != -1;
}

int dfs(int u, int fl)
{
	if(u == sink) return fl;

	for(int &i = pro[ u ]; i >= 0; i = nex[ i ]) {

		int v = to[ i ];

		if(flow[i] < cap[i] && dist[v] == dist[u] + 1) {

			int df = dfs(v, min(cap[ i ] - flow[ i ], fl) );

			if(df > 0) {

				flow[i] += df;
				flow[i ^ 1] -= df;

				return df;
			}
		}
	}
	return 0;
}

int dinic()
{
	int ret = 0;

	for(int i = 0; i < nEdge; i ++) flow[i] = 0;

	while( bfs() ) {

		for(int i = 0; i <= NN; i ++) pro[i] = fin[i];

		while(true) {

			int df = dfs(source, inf);
			if(df) ret += df;
			else break;
		}
	}
	return ret;
}

int a[MX];
vector<int> ans[MX];
int vis[MX], ed[300][300];

int main () {
#ifdef kfoozminus
//	freopen("in", "r", stdin);
//	freopen("out", "w", stdout);
#endif
	seive(100000);
	int odd = 0, even = 0, i, j;

	scanf("%d", &n);
	for(i = 0; i < n; i ++) {
		scanf("%d", &a[i]);
		if(a[i] & 1) odd ++;
		else even ++;
	}
	if(odd != even) {
		printf("Impossible\n");
		return 0;
	}

	source = 0;
	sink = n + 1;
	NN = sink;
	init();
	for(i = 0; i < n; i ++) {
		if(a[i] & 1) {
			addEdge(source, i + 1, 2);
		}
		else addEdge(i + 1, sink, 2);
		for(j = i + 1; j < n; j ++) {
			if(isPrime(a[i] + a[j])) addEdge(i + 1, j + 1, 1);
		}
	}
	int p = dinic();
	dbg(p);
	int in = -1;
	if(p == 2 * even) {
		//printf("Possible\n");
		for(i = 1; i <= n; i ++) {
			//while(true) {
				for(j = fin[i]; j >= 0; j = nex[j]) {
					if(cap[j] == 2) continue;
					if(vis[ to[j] ]) continue;
					if(flow[j] == 1) {
						ed[i][ to[j] ] = 1;
						ed[ to[j] ][i] = 1;
						dbg(i, to[j]);
						//i = to[j];
						//break;
					}
				}
			//}
		}
		memset(vis, 0, sizeof vis);
		for(i = 1; i <= n; i ++) {
			if(vis[i] == 0) in ++;
			while(vis[i] == 0) {
				vis[i] = 1;
				ans[in].PB(i);
				for(j = 1; j <= n; j ++) {
					if(vis[j]) continue;
					if(ed[i][j]) {
						i = j;
						break;
					}
				}
			}
		}
		printf("%d\n", in + 1);
		for(i = 0; i <= in; i ++) {
			printf("%d ", ans[i].size());
			for(auto it : ans[i]) printf("%d ", it);
			nl;
		}
	}
	else printf("Impossible\n");

//	timeStamp;
	return 0;
}