-
时间: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之后是素数
- 至多一个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;
}
时间: 2024-10-29 10:48:21