题目大意:
给出个数,输出他们其中两个数进行与运算后的最大值。
5
12 5 6 3 1
4
思路:
这道题比较简单,特别是40分的部分。直接两两枚举,记录进行与运算后的最大值即可。
#include <cstdio>
#include <iostream>
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;i<n;i++)
for (int j=i+1;j<=n;j++) //枚举
if (i!=j) ans=max(ans,a[i]&a[j]);
return printf("%d\n",ans)&0;
}
这道题100分就有点难拿了。我们必须在或的时间复杂度内完成。所以很容易想到贪心。这题贪心 由于数据水 是可以过的。但是如果遇到下面这种情况就WA了。
3
13 10 9
9
#include<cstdio>
#include<algorithm>
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方法,不过是优化,如果数据坑一点就TLE了。
#include<cstdio>
#include<algorithm>
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;i<n;i++)
if (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);
}
正解:
枚举输入数字最大值的后的结果,再枚举一次每个数,将与最大值的第位的数字不相同的都删除(为了保证答案最大),剩余两个数即为答案。
时间复杂度:
代码:
#include <cstdio>
#include <iostream>
#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<<i; //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;
}