本题就是给你一堆数,
然后给你一个x^k 要把这个x^k乘到哪个数,能使得这一堆数的 or运算之和最大
显然要让和最大 ,得让 被乘得到的数 最高位最大,所以全部数乘到一个数上
但是并不是选最大的一个数,例如
2 2 2
4 5
选四 是16|5 =21
选五 是 20|4 =20
其实我们可以证明 如果一堆数是 1 2 3 5 6 7 11 12 14 15 里
被选到的数一定在11 12 14 15里
因为他们二进制 比别的数都多了一个1
也就是 最后被选中的数一定在 最大的 2^(i-1)到2^i之间
然并卵,由于数据太小,直接求一遍前缀或和、求一遍后缀或和
再求出每一个数 ,除了自己以外其他所有数 的 或运算之和(在纸上一画就很清晰了)
例如pre[6]=1 2 3...6的或和
suf[8]=8 9 10 .....的或和
ans[7]=pre[6]|suf[8] 除了自己以外其他所有数 的 或运算之和
ans[i]=pre[i-1]+suf[i+1]
然后暴力试一遍就好了
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
__int64 tm[200005];
__int64 pre[200005];
__int64 suf[200005];
__int64 ans[200005];
int main()
{
// pr__int64f("%d %d \n",16|5,20|4);
__int64 n,k,x,i;
scanf("%I64d%I64d%I64d",&n,&k,&x);
for (i=1;i<=n;i++)
{
scanf("%I64d",&tm[i]);
}
for (i=1;i<=n;i++)
pre[i]=pre[i-1]|tm[i];
for (i=n;i>=1;i--)
suf[i]=suf[i+1]|tm[i];
for (i=1;i<=n;i++)
{
ans[i]=suf[i+1]|pre[i-1]; //���˵ڸ���Ԫ�� ����Ԫ�ص� ������ ֮��
}
__int64 tmp=1;
while(k--)
{
tmp*=x;
}
__int64 maxx=0;
for (i=1;i<=n;i++)
{
ans[i] |= (tmp*tm[i]);
if (ans[i]>maxx)
maxx=ans[i];
}
printf("%I64d\n",maxx);
return 0;
}