题目大意:
定义一个函数f(x,y) = (x∣y)−y。
给定一个长度为 n 数列 a,定义 f(f..f(f(a1,a2),a3),...an−1),an)
为这个数列的值。
现在,请你将数列改变一种顺序,使得最后的值最大。 输出你改变后的数列。
思路:
那么对整个序列的操作其实也就是。
f(f..f(f(a1,a2),a3),...an−1),an) = f(a1,(a2∣a3∣…∣an))
即从第一个数字的二进制中抠掉后面所有数字的二进制。
也容易得知,最后的结果跟 除第一个数字外 其它数字的顺序是无关的。
那么,我们只需要让第一个数字最大(含有最高二进制位的)就好了。
但是有共同的最高位时,这个最高位会被抠掉!
所以最终答案是:让含有最高且唯一的二进制位的数字到最前面就好啦。
代码:
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
#define endl '\n'
#define int long long
int n,g,b;
void solve()
{
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i];
for(int i = 30; i >= 0; i --) // 从最高位开始枚举
{
int tt = 1 << i, cnt = 0, idx = 0;
for(int j = 0; j < n; j ++) // 遍历每一个数
{
if(a[j] & tt) idx = j,cnt ++; // 如果这个数存在当前进制位
}
if(cnt == 1) // 并且所有数中只存在一个
{
swap(a[0], a[idx]);
break;
}
}
for (int i = 0; i < n; i ++ ) cout << a[i] << " ";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(0);
int T = 1;
//cin >> T;
while(T --)
{
solve();
}
return 0;
}