题目链接
题意:给定两个长度分别为 n , m ( 2 ≤ m , n ≤ 200 ) n,m(2 \le m,n \le 200) n,m(2≤m,n≤200)的序列 { a 1 , a 2 , … , a n } \{a_1,a_2,\ldots,a_n\} {a1,a2,…,an}、 { b 1 , b 2 , … , b m } \{b_1,b_2,\ldots,b_m\} {b1,b2,…,bm} ( 0 ≤ a i , b i < 2 9 ) (0\le a_i,b_i< 2^9) (0≤ai,bi<29)定义序列 { c 1 , c 2 , . . . , c n } \{c_1,c_2,...,c_n\} {c1,c2,...,cn}其中 c i = a i & b j ( 1 ≤ j ≤ m ) c_i=a_i \& b_j(1\le j \le m) ci=ai&bj(1≤j≤m),求 m i n ( c 1 ∣ c 2 ∣ . . . ∣ c n ) min(c_1|c_2|...|c_n) min(c1∣c2∣...∣cn)。
思路:由于 a i , b i a_i,b_i ai,bi的范围很小,答案总共 2 9 = 512 2^9=512 29=512种,可以考虑暴力求解,将 r e s = 0 , 1 , . . . , 511 res=0,1,...,511 res=0,1,...,511枚举过程中,利用
r e s = c 1 ∣ c 2 ∣ . . . ∣ c n res=c_1|c_2|...|c_n res=c1∣c2∣...∣cn,则 r e s ∣ c i = = r e s res|c_i==res res∣ci==res
这个性质,那么 ∀ i ∈ { 1 , 2 , 3 , . . . , n } , r e s ∣ c i = = r e s ( c i = a i & b j ) \forall i\in \{1,2,3,...,n\},res|c_i==res (c_i=a_i\&b_j ) ∀i∈{1,2,3,...,n},res∣ci==res(ci=ai&bj)就是题给要求的充分条件,从小到大枚举,得到的就是最小值了。
AC代码:
#include
#define ll long long
using namespace std;
int T = 1;
int a[205],b[205];
signed main() {
//cin>>T;
while (T--) {
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<m;i++) cin>>b[i];
for(int i=0;i<512;i++){
bool f=true;
for(int j=0;j<n;j++){
f= false;
for(int k=0;k<m;k++){
if(((a[j]&b[k])|i)==i){
f=true;
break;
}
}
//一旦有一个a_i找不得相匹配的b_j,就直接break
if(!f) break;
}
if(f){//认真分析代码可以发现,这里只有当所有的a_i都找到了相匹配的b_j才可到达
cout<<i<<endl;
return 0;
}
}
}
return 0;
}
写在最后:这题卡到结束也没想出来,一开始就想到 a i , b i a_i,b_i ai,bi都很小,可以按位来做,本来是想从高位到低位,依次来选 a i a_i ai可以与 b i b_i bi运算出0的数字,可是这样会有一个重复选到 a i a_i ai的问题。也有写过到头来还是行不通。看了别人的代码实在是太巧妙了只有所有的a_i,都有对应的可行的b_j,才是找到了合理答案,充分利用了上文提到的”充分条件“,这也是我一直纠结的”无法证明得到的就是最小的“,其实根本不需要证明这一点,直接从小开始搜,只考虑充分条件,简单好多。