vector + 二進制枚舉: Atcoder Dwacon 5th - B

鏈接:https://dwacon5th-prelims.contest.atcoder.jp/tasks/dwacon5th_prelims_b

題意:

給定一個長度爲n的序列,這n個數在序列中,一共會形成 n * (n + 1) / 2 個連續子序列,比如,1 2 3,可以形成:

{1}, {1,2},{1,2,3},{2},{2,3},{3},這 6 個連續子序列,構成這個子序列的某一元素索引不同即可視爲子序列不相同,比如:

1 2 1 2,可以形成,{1}, {1, 2}, {1, 2, 1}, {1, 2, 1, 2}, {2}, {2, 1}, {2, 1, 2}, {1}, {1, 2}, {2}。他們都被認爲是不同的。那麼這n個數所形成的這 n * (n + 1) / 2 個連續子序列,對應了 n * (n + 1) / 2 個序列元素和,比如 {1, 2, 1, 2} 的序列元素和就是1 + 2 + 1 + 2 = 6,從這n * (n + 1) / 2 個和中挑 k 個,打印這 k 個和 按位與的最大值。

思路:

這題我運用了vector,以及二進制枚舉的操作,

首先,先將每個位置的數能形成的所有子序列的元素和,存進當前vector中,操作如下:

void Init() {
    cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) {
        ll sum = 0;
        for(int j = i; j <= n; j++) {
            sum += a[j];
            vec.push_back(sum);
        }
    }
}

接下來我就進行二進制枚舉每一位,從高位到低位枚舉,看哪一位的1的個數不小於 k 個,那麼,我挑選出來的這k個數,肯定是當前位是1的這些數的子集,那麼我接下來只需要在當前位是1的這些數中繼續按位枚舉就行了,那麼具體實現就是,再開一個名爲 tmp 的 vector 去替換當前 vector,把當前位是1的數 push_back 進tmp,再 vec = tmp,進行替換。枚舉到 bit 位的時候,由於已經確定當前的 vector 中的這些數,第 bit 位是1的數的個數大於等於k個,那就說明這一位一定參與最後形成最大值的按位與了,換句話說,這一位,一定是答案當前的一位,所以每次 ans += 1ll << bit位即可。

具體操作如下:

void solve() {
    for(int bit = 59; bit >= 0; bit--) {
        int t = 0;
        int sz = vec.size();
        for(int i = 0; i < sz; i++) {
            ll dd = 1ll << bit;
            if(vec[i] & dd) t++;
        }
        if(t < k) continue;
        vector <ll> tmp;
        tmp.clear();
        for(int i = 0; i < sz; i++) {
            ll dd = 1ll << bit;
            if(vec[i] & dd) tmp.push_back(vec[i]);
        }
        vec = tmp;
        ans += 1ll << bit;
    }
}

 

我的AC代碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx = 1e6 + 7;
const int Inf = 1 << 30;
const ll INF = 1ll << 60;
#define mst(x) memset(x, 0, sizeof(x))
priority_queue <int> qua;
ll a[maxx];
vector <ll> vec;
int n, k;
ll ans;

void Init() {
    cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) {
        ll sum = 0;
        for(int j = i; j <= n; j++) {
            sum += a[j];
            vec.push_back(sum);
        }
    }
}

void solve() {
    for(int bit = 59; bit >= 0; bit--) {
        int t = 0;
        int sz = vec.size();
        for(int i = 0; i < sz; i++) {
            ll dd = 1ll << bit;
            if(vec[i] & dd) t++;
        }
        if(t < k) continue;
        vector <ll> tmp;
        tmp.clear();
        for(int i = 0; i < sz; i++) {
            ll dd = 1ll << bit;
            if(vec[i] & dd) tmp.push_back(vec[i]);
        }
        vec = tmp;
        ans += 1ll << bit;
    }
}

int main() {
    Init();
    solve();
    cout << ans << endl;
}

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