[思維] codeforces 665D. Simple Subset

題意:
給一個n個正整數序列a ,要找一個最大的子序列,使子序列裏任意兩個元素aiaj1<=i<j<=n)ai+aj 都是素數,要輸出這個子序列的大小和子序列的元素。
1<=n<=1000
1<=a[i]<=106
題解:
設一個滿足要求的子序列爲A
如果|A|<3 ,那麼只需用n2 的暴力即可。
如果|A|>=3 ,設abcA 中任意三個不同位置的數,那麼abc 必有2個數奇偶性相同。
ab 的奇偶性相同,那麼有下面兩種情況:
ab 爲偶數,那麼a+b 爲偶數。由於ab 都不爲0,顯然a+b 不是素數,所以這種情況不可能出現。
ab 爲奇數,那麼a+b 爲偶數。當a=b=1 時,a+b 爲素數,否則不爲素數。

結論:如果|A|>=3 ,那麼|A| 至少含有2個1,且即最多有一個數大於1。

所以首先判斷原數列a 有幾個1。
如果1的個數小於2,那麼|A|<3 ,採用第一種做法暴力。
如果1的個數大於等於2,那麼把所有1都加入答案,並且再判斷是否存在一個數x ,使得x+1 爲素數。根據前面的結論,最多可以加入一個大於1的數。

#include<bits/stdc++.h>
using namespace std;
const int N = 2000005;
int a[1005];
bool prime[N];
void init(){
    for(int i = 0; i < N; ++i) prime[i] = 1;
    for(int i = 2; i < N; ++i){
        if(!prime[i]) continue;
        for(int k = 2; i*k < N; ++k){
            prime[i*k] = 0;
        }
    }
}
int main(){
    init();
    int n;
    cin >> n;
    for(int i = 0; i < n; ++i) cin >> a[i];
    sort(a, a+n);
    int cot = 0;
    for(int i = 0; i < n; ++i) if(a[i] == 1) cot += 1;
    if(cot < 2){
        int flag = 0;
        for(int i = 0; i < n && !flag; ++i){
            for(int j = i+1; j < n && !flag; ++j){
                if(prime[a[i]+a[j]]){
                    printf("2\n%d %d", a[i], a[j]);
                    flag = 1;
                }
            }
        }
        if(!flag) printf("1\n%d", a[0]);
    }
    else{
        int flag = 0;
        for(int i = 0; i < n && !flag; ++i){
            if(a[i] != 1 && prime[a[i]+1]){
                printf("%d\n%d ", cot+1, a[i]);
                flag = 1;
            }
        }
        if(!flag) printf("%d\n", cot);
        for(int i = 0; i < cot; ++i) printf("1 ");
    }
    cout << endl;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章