[CodeForces] 578B "Or" Game

题意翻译

现在有n个数 a1,a2,a3,...,an,你最多可以进行k次操作,每次操作你可以将其中一个数乘以 x 。找出使得 a1∣a2∣...∣an最大的方法,"|"代表按位或。

题目解析

一眼很难然而简单的题。

要使按位或的结果最大,一定要让这些数字中最大的数 二进制的位数尽量大

证明:“或”意味着只要这一位有1结果中这一位就是1,基于事实100000 > 011111,我们可以把所有x都乘给一个数,让它去“占位”。

这样就很好想了。

我们只要枚举一下用哪个数去占位就可以了,加上巧妙的前缀和+后缀和优化就可以过了。

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

#define sum (pre[i]|(a[i]*tot)|suf[i])
const int MAXN = 200000 + 5;

int n,k,x;
long long a[MAXN];
long long pre[MAXN],suf[MAXN];//前缀 & 后缀 
long long tot,ans;

long long _max(long long x,long long y) {
    return x > y ? x : y;
}

int main() {
    scanf("%d%d%d",&n,&k,&x);
    for(int i = 1; i <= n; i++) {
        scanf("%lld",&a[i]);
    }
    for(int i = 1; i < n; i++) pre[i+1] = pre[i] | a[i];
    for(int i = n; i; i--) suf[i-1] = suf[i] | a[i];
//    for(int i = 1;i <= n;i++) {
//        cout<<"DEBUG: "<<pre[i]<<" "<<suf[i]<<endl;
//    }
    tot = 1;
    for(int i = 1; i <= k; i++) tot *= (long long)x;
    for(int i = 1; i <= n; i++) {
        ans = _max(sum,ans);
    }
    printf("%lld\n",ans);
}

 

posted @ 2018-08-21 16:41  Floatiy  阅读(377)  评论(0编辑  收藏  举报