CF578B "Or" Game(贪心)题解

题意

现在有n个数\(a_1,a_2,a_3,...,a_n\) 。你最多可以进行k次操作,每次操作你可以将其中一个数乘以\(x\),使得\(a_1|a_2|...|a_n\) 最大。

算法

贪心+前缀后缀

思路

首先明确:答案的这\(k\)\(\times x\)操作用都会在同一个数身上。因为\(x\)大于\(2\),所以每次相乘都会使得该数的二进制为至少左移一位,或起来以后必然会使答案更优。

如何快速求出每一个数操作之后的答案?

利用前缀后缀思想,维护前缀或与后缀或,这样就可以在枚举出修改的数以后\(O(1)\)求出答案了。

参考代码

#include <cstdio>
#include <algorithm>
#define LL long long

using namespace std;

const int maxn = 2e5 + 10;
int n,a[maxn],k,x;
LL pre[maxn],bac[maxn],Ans;

int main(){
    scanf("%d%d%d", &n, &k, &x);
    for(int i = 1; i <= n; ++ i) scanf("%d", a + i);
    for(int i = 1; i <= n; ++ i) pre[i] = pre[i - 1] | a[i];
    for(int i = n; i >= 1; -- i) bac[i] = bac[i + 1] | a[i];
    for(int i = 1; i <= n; ++ i){
        LL ret = a[i];
        for(int j = 1; j <= k; ++ j) ret *= x;
        Ans = max(Ans, ret | pre[i - 1] | bac[i + 1]);
    }
    printf("%lld\n", Ans);
    return 0;
}
posted @ 2020-11-26 20:47  When_C  阅读(83)  评论(0编辑  收藏  举报