给出 n n 个数,输出他们其中两个数进行与运算后的最大值。
Input I n p u t
5
12 5 6 3 1
Output O u t p u t
4
这道题比较简单,特别是40分的部分。直接 O(n2) O ( n 2 ) 两两枚举,记录进行与运算后的最大值即可。
#include
#include
using namespace std;
int n,a[10001],ans,maxn;
int main()
{
freopen("sword.in","r",stdin);
freopen("sword.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=1;ifor (int j=i+1;j<=n;j++) //枚举
if (i!=j) ans=max(ans,a[i]&a[j]);
return printf("%d\n",ans)&0;
}
这道题100分就有点难拿了。我们必须在 O(n) O ( n ) 或 O(nlongn) O ( n l o n g n ) 的时间复杂度内完成。所以很容易想到贪心。这题贪心 由于数据水 是可以过的。但是如果遇到下面这种情况就WA了。
Input I n p u t
3
13 10 9
Output O u t p u t
9
#include
#include
using namespace std;
int n,a[1000001],ans=-1;
bool cmp(int x,int y) {return x>y;}
int main()
{
freopen("sword.in","r",stdin);
freopen("sword.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1,cmp); //从大到小排序
for (int i=1;i<=n;i++)
{
if ((a[i]&a[i+1])<=ans) break;
ans=a[i]&a[i+1]; //贪心,每次将相邻的两个数字进行与运算
}
printf("%d",ans);
}
这道题还有另一种AC方法,不过是 O(n2) O ( n 2 ) 优化,如果数据坑一点就TLE了。
#include
#include
using namespace std;
int n,answ,a[1000005];
bool cmp(int x,int y)
{
return x>y;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1,cmp);
for (int i=1;iif (a[i]>answ){ //剪枝
for (int j=i+1;j<=n;j++)
if ((a[i]&a[j])>=answ) answ=(a[i]&a[j]);
}
printf("%d",answ);
}
枚举输入数字最大值的 log2 l o g 2 后的结果,再枚举一次每个数,将与最大值的第 i i 位的数字不相同的都删除(为了保证答案最大),剩余两个数即为答案。
时间复杂度: O(n) O ( n )
#include
#include
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
int n,a[2000001],sum,o,ans;
int main()
{
fre(sword);
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
for (int i=30;i>=0;i--) //枚举,log之后最多不会超过30位。
{
sum=0;
o=1<//2^i
for (int j=1;j<=n;j++)
if ((a[j]&ans)==ans&&(a[j]&o)==o) //符合要求
sum++;
if (sum>1) ans+=o; //能匹配
}
return printf("%d\n",ans)&0;
}