ARC080F

没有证明,但没人找到反例当然就能用啊
将序列差分,特判一下0。
考虑消掉两个为1的位置i,j 如果|i−j|是奇质数,那么需要1次操作
如果|i−j|是偶数,那么根据哥德巴赫猜想,大于等于6的偶数都能分解为两个奇质数之和,那么只需要两次。2的话可以5-3得到,4可以7-3得到
如果|i−j|是奇合数,那么需要3次。一次将它变成偶数,然后同第二次
将所有的差分后的位置按照奇和偶分成两组
我们尽量要让一次操作的多

那么差为奇质数的连边,跑二分图最大匹配

剩下的尽量同组匹配(差为偶数)
最后每组最多剩下一个,直接匹配即可
code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
const int N=102;
int n,cnp,cnj,cnt,og[N],hx[N<<1],fir[N<<1],prm[460];
bool npr[3200];
struct edge{
	int to,wi,nx;
}eg[N*N];

inline void add(int a,int b,int v){
	static int cnt=1;
	eg[++cnt]=(edge){b,v,fir[a]};
	fir[a]=cnt;
	eg[++cnt]=(edge){a,0,fir[b]};
	fir[b]=cnt;
}

inline char get_c(){
	static char buf[20000],*h,*t;
	if(h==t){
		t=(h=buf)+fread(buf,1,20000,stdin);
	}
	return h==t?EOF:*h++;
}

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

inline void init(){
	npr[1]=1;
	for(int i=2;i<3200;++i){
		if(!npr[i]) prm[++cnp]=i;
		for(int j=1;j<=cnp&&i*prm[j]<3200;++j){
			npr[i*prm[j]]=1;
			if(i%prm[j]==0) break;
		}
	}
}

inline bool ispr(int x){
	if(x<3200) return !npr[x];
	int sq=sqrt(x)+1;
	for(int i=1;prm[i]<=sq;++i){
		if(x%prm[i]==0) return 0;
	}
	return 1;
}

namespace F{
	int dep[N<<1],que[N<<1],cur[N<<1];

	inline bool bfs(){
		memset(dep,0,sizeof(dep));
		int hd=0,tl=1;
		dep[0]=1;
		while(hd!=tl){
			int x=que[hd++];
			for(int i=cur[x]=fir[x];i;i=eg[i].nx){
				int y=eg[i].to;
				if(eg[i].wi&&!dep[y]){
					dep[y]=dep[x]+1;
					que[tl++]=y;
				}
			}
		}
		return dep[(N<<1)-1];
	}

	int dfs(int x,int t){
		if(x==(N<<1)-1) return t;
		int tp,tt=t;
		for(int &i=cur[x];i;i=eg[i].nx){
			int y=eg[i].to,v=eg[i].wi;
			if(v&&tt&&dep[x]+1==dep[y]&&(tp=dfs(y,std::min(v,tt)))){
				eg[i].wi-=tp;
				eg[i^1].wi+=tp;
				tt-=tp;
				if(!tt) break;
			}
		}
		return t-tt;
	}
}

int main(){
#ifndef ONLINE_JUDGE
//	freopen("c.in","r",stdin);
#endif
	init();
	n=nxi();
	for(int i=1;i<=n;++i){
		og[i]=nxi();
	}
	std::sort(og+1,og+n+1);
	og[0]=-1;
	for(int i=1;i<=n;++i){
		if(og[i]-og[i-1]>1){
			if(og[i-1]+1) hx[++cnt]=og[i-1]+1;
			hx[++cnt]=og[i];
		}
	}
	hx[++cnt]=og[n]+1;
	for(int i=1;i<=cnt;++i){
		if(hx[i]&1) ++cnj;
		if(hx[i]&1) add(0,i,1);
		else add(i,(N<<1)-1,1);
		for(int j=i+1;j<=cnt;++j){
			int p=hx[j]-hx[i];
			if((p&1)&&ispr(p)){
				if(hx[i]&1) add(i,j,1);
				else add(j,i,1);
			}
		}
	}
	int ans=0;
	while(F::bfs()){
		ans+=F::dfs(0,N);
	}
	printf("%d\n",cnt-ans+((cnj-ans)&1));
	return 0;
}