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;
}

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