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 }
View Code
非做顽石不可,哪管他敬仰暗唾
原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11454103.html