MZOJ #77 与
分析
因为要求的是“与”的最大值
O(n2)的暴力从数据看不可行,但其实是可行的
看代码:
这样写代码的话如果不是特别构造数据,一般都能过
时间比正解慢不了多少,有时甚至还快一点
接下来我们说正解
怎么想到正解的呢?
首先,“&”的特征是结果包含于原数且为两数共有
既然枚举原数不行,我们试试枚举答案,然后统计是否有两个以上的数包含就好
但是a[i]<=1000000000
当然,不能一个一个枚举
再想,“&”是二进制运算,当然按位枚举比十进制的枚举要快的多
怎么枚举呢?
想想二进制数的特征,当然位数越高,答案越大,后面位数再大,不可能比高位的要大
所以,贪心;
贪心的从高位开始枚举,就可以得到最大答案
就像这样:
check函数是用于检验是否合法的
代码
1 /************************** 2 User:Mandy.H.Y 3 Language:c++ 4 Problem:and 5 Algorithm: 6 **************************/ 7 8 #include<bits/stdc++.h> 9 10 using namespace std; 11 12 const int maxn = 3e5 + 5; 13 14 int n,ans = 0,s = 0; 15 int a[maxn]; 16 17 template<class T>inline void read(T &x){ 18 x = 0;bool flag = 0;char ch = getchar(); 19 while(!isdigit(ch)) flag |= ch == '-',ch = getchar(); 20 while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar(); 21 if(flag) x = -x; 22 } 23 24 template<class T>void putch(const T x){ 25 if(x > 9) putch(x / 10); 26 putchar(x % 10 | 48); 27 } 28 29 template<class T>void put(const T x){ 30 if(x < 0) putchar('-'),putch(-x); 31 else putch(x); 32 } 33 34 void file(){ 35 freopen("and.in","r",stdin); 36 freopen("and.out","w",stdout); 37 } 38 39 void readdata(){ 40 read(n); 41 for(int i = 1;i <= n; ++ i) read(a[i]); 42 } 43 44 bool cmp(int a,int b){ 45 return a > b; 46 } 47 48 bool check(int x){ 49 int tot = 0; 50 for(int i = 1;i <= n; ++ i){ 51 if((a[i] & x) == x) tot ++; 52 if(tot >= 2) return 1; 53 if(a[i] < x) break; 54 //事先将a从大到小排序 55 } 56 return tot >= 2; 57 } 58 59 void work(){ 60 sort(a + 1,a + n + 1,cmp); 61 for(int i = 30;i >= 0; -- i){ 62 if(check(ans | ((1 << i)))) ans |= (1 << i); 63 } 64 put(ans); 65 } 66 67 int main(){ 68 // file(); 69 readdata(); 70 work(); 71 return 0; 72 }
非做顽石不可,哪管他敬仰暗唾