时间:2016-04-27 15:16:14 星期三
题目编号:[2016-04-27][codeforces][665D - Simple Subset]
题目大意:给定n个数字的集合A,问子集最大能有多大,使得子集中两两之和是素数,输出大小和任一这样子集
分析:
- 至多一个1:
- 首先 从A取任意3个数
- 如果这3个数字中至多1个 1
- 由容斥原理可知,一定有两个数之和是偶数,并且这个偶数之和大于2(一定不是素数),所以答案子集中,大于1的数字至多只能有两个,
- 推广到整个A,就是如果A中至多含有1个1,时,子集最多只有2个数字,那么答案就是
- 没有两个数字之和是素数,
- 存在某两个数字之和是素数,(即使有多对,只能输出一对)
- 如果多个1,那么答案就有
- 全部都是1
- 除了1之外,还有一个数字,这个数字+1之后是素数
#include<cstdio>#include<cstring>using namespace std;const int maxn = 1E3 + 10;const int maxp = 1E6*2 + 10;int isnpri[maxp],a[maxn];void getpri(){ memset(isnpri,0,sizeof(isnpri)); for(int i = 2 ; i < maxp + 10 ; ++i){ if(isnpri[i]) continue; for(int j = i * 2 ; j < maxp; j += i){ isnpri[j] = 1; } }}int main(){ getpri(); int n,cnt1 = 0; scanf("%d",&n); for(int i = 0 ; i < n ; ++i){ scanf("%d",&a[i]); if(a[i] == 1) ++cnt1; } if(cnt1 > 1){ for(int i = 0 ; i < n ; ++i){ if(a[i] != 1 && !isnpri[a[i] + 1]){ printf("%d\n%d",cnt1 + 1,a[i]); for(int j = 0 ; j < cnt1;++j){ printf(" 1"); } return 0; } } printf("%d\n",cnt1); for(int j = 0 ; j < cnt1;++j){ printf("1 "); } return 0; } for(int i = 0 ; i < n ; ++i){ for(int j = 0 ; j < n ; ++j){ if(i != j && !isnpri[a[i] + a[j]]){ printf("2\n%d %d",a[i] , a[j]); return 0; } } } printf("1\n%d",a[0]); return 0;}