Codeforces Round #556 (Div. 2) -- C 1150C - Prefix Sum Primes

C:https://codeforces.com/contest/1150/problem/C

題意:給你n個1或者2,你可以任意排序,要求排好序後的序列的所有前綴和中,含有的素數最多。

比賽時思路:先打個素數表,然後記錄保存每一個的素數,每次算出目前前綴和與下一個素數之間的差值,對於這個差值,如果剩下的1和2都加起來都填不了這個 差值,就可以跳出循環。如果可以填補這個差值,再分奇偶進行討論,如果是奇數:判斷是否含有1,如果沒1了,那麼就跳過這個素數,求出下一個素數與當前前綴和的差值。在填補差值時,優先用2來填充,2用完了再用1來填充。

代碼:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#define Fin             freopen("in.txt","r",stdin)
#define Fout            freopen("out.txt","w",stdout)
#define Case(T)         int T;for(scanf("%d",&T);T--;)
#define fo(i,a,b)              for(int i = a; i < b; ++i)
#define fd(i,a,b)              for(int i = a; i >= b; --i)
#define me(a,b) memset(a,b,sizeof(a))
#define fi(a,n,val)    fill(a,a+n,val)
#define Scand(n)       scanf("%d",&n)
#define Scand2(a,b)     scanf("%d%d",&a,&b)
#define Scand3(a,b,c)     scanf("%d%d%d",&a,&b,&c)
#define Scand4(a,b,c,d)     scanf("%d%d%d%d",&a,&b,&c,&d)
#define Scans(s)       scanf("%s",s)
#define random(a,b)    a+rand()%(b-a+1)
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b ? gcd(b,a%b): a; }
const int maxn = 4e5 + 50;
const int INFint = 0xffffff;
const ll INFll = (ll)1e18;

#ifndef ONLINE_JUDGE

#endif // ONLINE_JUDGE

inline int readint(){
    int sgn = 1; int sum = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if(ch == '-')   sgn = -sgn;
        ch = getchar();
    }
    while ('0' <= ch && ch <= '9') {
        sum = sum*10+(ch-'0');
        ch = getchar();
    }
    return sgn*sum;
}

inline ll readll(){
    ll sgn = 1; ll sum = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if(ch == '-')   sgn = -sgn;
        ch = getchar();
    }
    while ('0' <= ch && ch <= '9') {
        sum = sum*10+(ch-'0');
        ch = getchar();
    }
    return sgn*sum;
}

int n;
vector<int> prime;
bool notprime[maxn];
int arr[maxn];
int cnt1, cnt2;
int sum = 0;
vector<int> ans;

void init(){
    memset(notprime, false, sizeof(notprime));
    notprime[0] = notprime[1] = true;
    for(int i = 2; i < maxn; i++)
        if(!notprime[i]){
            if(i > maxn / i)continue;//防止後面i*i溢出 (或者i,j用long
            //直接從i*i開始就可以,小於i倍的已經篩選過了,注意是j+=i
            for(int j = i * i; j < maxn; j += i)
                notprime[j] = true;
        }
    for(int i = 0; i < maxn; ++i)
        if(!notprime[i])
            prime.push_back(i);
}

int main()
{
    #ifndef ONLINE_JUDGE
        //Fin;
    #endif // ONLINE_JUDGE
    init();
    n = readint();
    cnt1 = 0;   cnt2 = 0;
    for(int i = 0; i < n; ++i){
        arr[i] = readint();
        if(arr[i] == 1)
            cnt1++;
        else if(arr[i] == 2)
            cnt2++;
    }
    int Index = 0;
    sum = 0;
    int now = prime[Index++];
    while(cnt1 != 0 || cnt2 != 0){
        int dis = now - sum;
        if(dis%2){
            if(cnt2*2 + cnt1 < dis) break;
            if(cnt1 <= 0){
                now = prime[Index++];
                continue;
            }
            int need = dis/2;
            if(cnt2 >= need){
                for(int i = 0; i < need; ++i)
                    ans.push_back(2);
                cnt2 -= need;
                ans.push_back(1);
                cnt1 -= 1;
            }else{
                for(int i = 0; i < cnt2; ++i)
                    ans.push_back(2);
                for(int i = 0; i < (dis - cnt2*2); ++i)
                    ans.push_back(1);
                cnt1 -= (dis - cnt2*2);
                cnt2 = 0;
            }
        }else{
            if(cnt2*2 + cnt1 < dis) break;
            int need = dis/2;
            if(need <= cnt2){
                for(int i = 0; i < need; ++i)
                    ans.push_back(2);
                cnt2 -= need;
            }else if(cnt2*2 + cnt1 >= dis){
                for(int i = 0; i < cnt2; ++i)
                    ans.push_back(2);
                for(int i = 0; i < (dis - cnt2*2); ++i)
                    ans.push_back(1);
                cnt1 -= (dis - cnt2*2);
                cnt2 = 0;
            }else{
                break;
            }
        }
        sum = now;
        now = prime[Index++];
    }
    for(int i = 0; i < cnt1; ++i)
        ans.push_back(1);
    for(int i = 0; i < cnt2; ++i)
        ans.push_back(2);
    int Size = ans.size();
    for(int i = 0; i < Size; ++i)
        cout << ans[i] << ' ';
    return 0;
}

賽後看大佬的思路:首先,你要知道:除了2和3之間的差值爲1(是一個奇數)之外,其他任何兩個素數之間的差值一定是一個偶數!!!!(因爲,除了2之外,素數都是奇數)。那麼這題就很easy了啊!既然後面的差值都是偶數,那麼貪心就完事了:優先用2填充,2用完了再用1。當然,對於前面的2和3,在前面先用2和1就行。

代碼:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#define Fin             freopen("in.txt","r",stdin)
#define Fout            freopen("out.txt","w",stdout)
#define Case(T)         int T;for(scanf("%d",&T);T--;)
#define fo(i,a,b)              for(int i = a; i < b; ++i)
#define fd(i,a,b)              for(int i = a; i >= b; --i)
#define me(a,b) memset(a,b,sizeof(a))
#define fi(a,n,val)    fill(a,a+n,val)
#define Scand(n)       scanf("%d",&n)
#define Scand2(a,b)     scanf("%d%d",&a,&b)
#define Scand3(a,b,c)     scanf("%d%d%d",&a,&b,&c)
#define Scand4(a,b,c,d)     scanf("%d%d%d%d",&a,&b,&c,&d)
#define Scans(s)       scanf("%s",s)
#define random(a,b)    a+rand()%(b-a+1)
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b ? gcd(b,a%b): a; }
const int maxn = 2e5 + 50;
const int INFint = 0xffffff;
const ll INFll = (ll)1e18;

#ifndef ONLINE_JUDGE

#endif // ONLINE_JUDGE

inline int readint(){
    int sgn = 1; int sum = 0;
    char ch = getchar();
    while(!('0' <= ch && ch <= '9')){
        if(ch == '-')   sgn = -sgn;
        ch = getchar();
    }
    while('0' <= ch && ch <= '9'){
        sum = sum * 10 + (ch - '0');
        ch = getchar();
    }
    return sgn * sum;
}

inline ll readll(){
    ll sgn = 1; ll sum = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if(ch == '-')   sgn = -sgn;
        ch = getchar();
    }
    while ('0' <= ch && ch <= '9') {
        sum = sum*10+(ch-'0');
        ch = getchar();
    }
    return sgn*sum;
}

int n;
int arr[maxn];
int cnt1, cnt2;

int main()
{
    #ifndef ONLINE_JUDGE
        //Fin;
    #endif // ONLINE_JUDGE
    cnt1 = cnt2 = 0;
    n = readint();
    for(int i = 0; i < n; ++i){
        arr[i] = readint();
        if(arr[i]%2)
            cnt1++;
        else
            cnt2++;
    }
    if(cnt2){
        cout << 2;
        cnt2--;
    }
    if(cnt1){
        cout << ' ' << 1;
        cnt1--;
    }
    while(cnt2){
        cout << ' ' << 2;
        cnt2--;
    }
    while(cnt1){
        cout << ' ' << 1;
        cnt1--;
    }
    return 0;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章