题目大意
定义$f(x, y) = (x|y)-y$,有一个数组$A$可以为$[a_1, a_2, …, a_n]$,重排$A$中的元素使得$f(f(…f(f(a_1,a_2),a_3),…a_{n-1}),a_{n})$的值最大,输出重排后的$A$
题解
思路1:
对于式子$f(x, y)=(x|y)-y$,考虑$x$和$y$的二进制位
当$y$的第$i$位是1的时候,$x$的$i$位是0还是1对结果的第$i$位都没有影响,结果的第$i$位都是0
当$y$的第$i$位是0的时候,结果的第$i$位等于$x$的第$i$位
最终的结果只和把谁放在$A$中第一的位置有关,也就是说对于$a_1, a_2, a_3, …, a_n$如果想把其中的一个数字$x$放在第一个,那么当$x$的第$i$位是1的时候,数组中的其他数字的第$i$位必须全部是0函数的结果的第$i$位置才能取得1,如果$x$的第$i$位是0的话,那么函数的结果的第$i$位一定是0,所以对与每一个$a_i$我们都算一下函数的最终结果,然后把最大的位置的那个放在第一个即可。
以上思路来自Akura_Mea
1 |
|
思路2:
官方题解的做法是$f(x, y) = (x|y)-y = x \& (\sim y)$,
要求$f(f(…f(f(a_1,a_2),a_3),…a_{n-1}),a_{n})$,
等价于求$a_1\&(\sim a_2)\&(\sim a_3)\&…\&(\sim a_{n-1})\&(\sim a_{n})$,
从式子可以看出最终的结果只和哪一个放在第一的位置有关,所以维护一个取反的前缀和还有一个取反的后缀和,就能算出哪一个放在$a_1$的位置得到的最终结果最大
1 | def wrapper(func): |
总结
可以看出上面两种思路实现方法不一样,但是原理都一样