子序列的权值最小值
题目描述
给定一个长度为 n 的数组 a ,求数组所有非空子序列权值的最小值。
定义子序列 ai , aj , … , ak 的权值为 ai&aj&…&ak
其中 & 为二进制中的按位与
按位与的定义:链接:https://ac.nowcoder.com/acm/contest/49030/A
输入描述
第一行包含一个正整数 n(1≤n≤20) 代表数组长度。
第二行包含 n 个正整数 ai(1≤ai≤109) 代表数组中每个数的值。
输出描述
输出数组中所有飞控子序列权值的最小值。
示例1
输入
6
1 1 4 5 1 4
输出
0
备注
子序列不一定连续
题解
按位与的运算规律:
1&1=1
1&0=0
0&1=0
0&0=0
同 1 得 1,有 0 得 0。即如果某位上的数为 0 ,与其他任何 n-1 个数按位与后,该位上的数仍为 0 ;所以除非参与运算的所有数在某位上全为 1 ,得到的结果在该位上才能为 1 。
想要得到最小值,需要每位上的数都是最小值,所以将序列中所有的数按位与,结果即为最小值。
证明:如果所有数在某位上都为 1 ,则挑出其中任意 k 个按位与后仍为 1 ,且是最小值,如果该位上的最小值可以是 0 ,则在该位上至少存在一个 0 ,与条件“所有数在该位上都为 1 ”相悖,所以 1 就是最小值;如果在某位上存在 0 ,则与其他 n-1 个数按位与后该为的结果仍为 0 ,且是最小值。
综上,将序列中所有的数按位与所得结果就是最小值。
代码
#include <iostream>
using namespace std;
const int N = 27;
int a[N];
int main(void)
{
int n;
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
int ans = a[1];
for (int i = 2; i <= n; ++i) ans &= a[i];
cout << ans;
return 0;
}