与运算 递归
【题目描述】
给定 n 个数,找出两个,使得它们经过与运算后结果最大。
注意,选出来的两个数在原数组中的位置不能一样,但是数值可以一样。
【输入格式】
第一行一个整数 n,表示数字个数。
第二行 n 个数,表示给定的数。
【输出格式】
一个整数表示答案。
【样例输入】
3
1 2 1
【样例输出】
1
【数据范围】
对于 20%的数据点,n <= 1000
对于另外 20%的数据点,只有 0 和 1
对于 100%的数据点,n <= 100000, 0 <= 数值 <= 10^9
我们知道当当前位都是1时与出来才是1,所以我们考虑从位数高的地方开始统计。
如果当前位数字数量大于2,那么就符合条件,然后递归继续找低位有没有满足条件的。
代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define ll long long #define il inline #define db double using namespace std; il int gi() { int x=0,y=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') y=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*y; } int point[100045]; int stackk[100045]; int stack[100045]; int ci[45]; int num[31][100005]; int s[31]; int er[100005][31]; int check(int now,int tot)//now是当前2的几次方,tot是有多少数满足 { //printf("now=%d tot=%d\n",now,tot); if(now==0) return 1; for(int next=1;now-next>=0;next++) { int cnt=0; for(int i=1;i<=tot;i++) if(er[stack[i]][now-next]) stackk[++cnt]=stack[i]; if(cnt>=2) { for(int i=1;i<=cnt;i++) stack[i]=stackk[i]; return ci[now]+check(now-next,cnt); } } return ci[now]; } int main() { freopen("and.in","r",stdin); freopen("and.out","w",stdout); int n=gi(); ci[0]=1; for(int i=1;i<=30;i++) ci[i]=ci[i-1]*2; int x; bool flag=0; for(int i=1;i<=n;i++) { x=gi(); if(x!=0) flag=1; point[i]=x; for(int j=30;j>=0;j--) if(x>=ci[j]) { x-=ci[j]; er[i][j]=1; num[j][++s[j]]=i; } } int now=30; while(s[now]<2&&now>=0) { now--; } for(int i=1;i<=s[now];i++) stack[i]=num[now][i]; if(flag) printf("%d\n",check(now,s[now])); else printf("0\n"); return 0; }
PEACE