Codeforces 665D Simple Subset [简单数学]

题意:

给你n个数,让你从中选一个子集要求子集中的任何两个数相加都是质数。

思路:

一开始把自己坑了,各种想,后来发现一个简单的性质,那就是两个数相加的必要条件是这两个数之中必定一个奇数一个偶数,(除了含有1 集合以外,1+1等于2也是质数)。

考虑两种情况,有1存在和1不存在这两种。

很显然1存在的情况下,所有的1都可以同时在集合中出现,要想集合最大不能加奇数,只能加偶数,那么我们看原始集合中是否有偶数加一是素数。

不考虑1的情况下,这样的子集最大是2,只有存在一个奇数一个偶数相加是质数的情况下才存在个数是2的子集。

比较下输出答案就好了==

#include<bits/stdc++.h>
using  namespace std;
int prime[2000010];
int tmp[2000010];
int ji[1005],ou[1005];
int num[1005];
bool can[1005][1005],goon[1005];
void fprime()
{
    int atmp=0,i,j;
    for(i=2;i<2000010;i++)
    {
        if(!prime[i])
        {
            tmp[atmp++]=i;
        }
        for(j=0;j<atmp;j++)
        {
            if(i*tmp[j]>2000005)
                break;
            prime[i*tmp[j]]=1;
            if(i%tmp[j]==0)
                break;
        }
    }
}
int main()
{
    fprime();
    int n,tmp,num_one=0,num_ji=0,num_ou=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&tmp);
        if(tmp==1)num_one++;
        else if(tmp&1)ji[num_ji++]=tmp;
        else ou[num_ou++]=tmp;
    }
    bool have_jiou=0;
    int ans_ji,ans_ou;
    for(int i=0;i<num_ji;i++){
        for(int j=0;j<num_ou;j++){
            if(prime[ji[i]+ou[j]]==0){
                have_jiou=1;
                ans_ji=ji[i];ans_ou=ou[j];
                break;
            }
        }
    }
    bool have_oneou=0;
    int ans_oneou;
    for(int i=0;i<num_ou;i++){
        if(prime[ou[i]+1]==0){
            have_oneou=1;
            ans_oneou=ou[i];
            break;
        }
    }
    num_one+=have_oneou;
    if(num_one>=2){
        printf("%d
",num_one);
        if(have_oneou)printf("%d ",ans_oneou);
        for(int i=0;i<num_one-have_oneou;i++)printf("1 ");
    }
    else if(have_jiou){
        printf("2
%d %d",ans_ou,ans_ji);
    }
    else{
        printf("1
");
        if(num_ou)printf("%d
",ou[0]);
        else if(num_ji)printf("%d
",ji[0]);
        else printf("1
");
    }
}
原文地址:https://www.cnblogs.com/tun117/p/5421768.html