题意:数组a和b,问1<=a<=n,1<=j<=m,将所有的ci=a[i]&b[j]取或的最小值为多少,i每个只取一次,j每个可以取任意次。
这题我没做出来,所以我按官方题解来,这里稍微将一下过程。在整个过程中都是用的或运算和与运算,转化为二进制后最高位是不变的,ai,bi<29,也就是说运算后的最大值为29-1,最后用的是或运算,所以ans>=ci,而且有ci|ans=ans。
我们令ans=29-1,所有的进制位都为1,我们从高位到低位讨论是否要该为由1变为0,判断条件为是否对于所有的ai,都存在bj,使得a[i]&b[j]|ans=ans;如果条件符合,则可以让所讨论的位数的1变为0,否则不变。改变所在进制位的1用ans和只有该进制位为1的数异或所得。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 222;
int arr1[N], arr2[N];
int n, m;
bool solve(int x) {
for (int i = 1; i <= n; i++) {
bool sign = false;
for (int j = 1; j <= m; j++) {
if (((arr1[i] & arr2[j]) | x) == x) {
sign = true;
break;
}
}
if (!sign) return false;
}
return true;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &arr1[i]);
}
for (int i = 1; i <= m; i++) {
scanf("%d", &arr2[i]);
}
int ans = (1 << 9)-1;
for (int k = 8; k >= 0; k--) {
if (solve(ans ^ (1 << k))) ans ^= (1 << k);
}
printf("%d\n", ans);
}