CF1635A Min Or Sum
发个严谨点的证明罢。
引理
$$ x|y≤x+y $$ 先搞个真值表出来:
$a$ | $b$ | $a\vert b$ | $a+b$ |
---|---|---|---|
1 | 1 | 1 | 2 |
1 | 0 | 1 | 1 |
0 | 1 | 1 | 1 |
0 | 0 | 0 | 0 |
可以看出,对于任意二进制位 $a,b$,$a|b≤a+b$。
设 $x$ 的第 $k$ 个二进制位为 $x_k$,则对于任意 $x,y$,$x_k|y_k≤x_k+y_k$。
(如果 $x,y$ 位数不同,则在位数少的数前面补 $0$)
我们有:$$ x+y=\sum\limits2^k(x_k+y_k),x|y=\sum\limits2^k(x_k|y_k) $$ 作差法比较大小:$$ \begin{aligned} (x+y)-(x|y)&=\sum\limits2^k(x_k+y_k)-\sum\limits2^k(x_k|y_k)\\ &=\sum\limits2^k[(x_k+y_k)-(x_k|y_k)]≥0 \end{aligned} $$ 所以 $x|y≤x+y$。
思路
因为 $x|0=x$,所以可以把 $a_i,a_j$ 变成 $a_i|a_j,0$。
($a_i|a_j=(a_i|a_j)|0$,符合题目要求)
这样做之后,原来的和 $a_i+a_j$ 就变成了 $a_i|a_j$,
根据引理可以知道 $a_i|a_j≤a_i+a_j$,比原来更优。
于是就可以对 $a_1$ 和 $a_{i∈[2,n]}$ 都执行一遍这个操作,
原数列就变成 $a_1|a_2|a_3|...|a_n,0,0,0...$,不含有加法,是最小值。
代码
#include <cstdio>
int T, n, s, t;
int main()
{
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);s = 0;
while(n--) scanf("%d", &t), s |= t;
printf("%d\n", s);
}
return 0;
}