cf#320 Div.2 Problem D "Or" Game

来源:互联网 发布:矩阵的用途 编辑:程序博客网 时间:2024/05/17 22:58

本题就是给你一堆数, 

然后给你一个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;} 

0 0
原创粉丝点击