题意:
给你n个数,b[1],b[2],b[3].......,让你重新排列,使a[i]的值递增
a[i]和b的关系:
a[i] = b[1]^b[2]^b[3]^....^b[i];
首先说异或 因为是递增,所以1^0 0^0 1^1都不满足条件
只有0^1满足条件
1^0 == 1 相当于没有增长
0^1 == 1 这才相当于增长了1
再看 a=00 01 01 10
b=00 10 11 10
这两个二进制数a,b进行异或
对于第一位 大家都等于0 异或出来相当于没变
第二位 大家都等于1 异或出来相当于少1
第三位。。。。。
第四位 a第四位等于0 b第四位等于1 两个数异或 相当于b的这一位没有改变
第五位 a第五位等于1 b第五位等于0 两个数异或 b的这一位变成1
所以只要选择a的最高位等于1 b的这一位等于0的情况进行异或
但是为什么要选择最高位:
因为只要最高位进行了增加 比他低的位无论加1还是减1都不会影响异或后的大小关系
可惜就是这样我也没想出来,想到了0和1的异或关系和一位一位去算
但是没做出来 可惜了
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const long long maxn = 2e5+5; const long long N = (long long)1<<59; long long a[maxn]; long long b[maxn]; vector<long long> bit[68]; int main() { long long n,i,j,k; long long x; scanf("%lld",&n); for(i=0;i<n;++i) { scanf("%lld",b+i); x = 1; for(j = 59;j>=0;--j) { if((x<<j)&b[i]) { bit[j].push_back(b[i]); break; } } } x = 0; for(i=0;i<n;++i) { bool flag = false; for(j=0;j<60;++j) { if(((x&((long long)1<<j)) == 0) && bit[j].size()) { a[i] = bit[j][bit[j].size()-1]; x ^= bit[j][bit[j].size()-1]; bit[j].pop_back(); flag = true; break; } } if(!flag) { printf("No "); return 0; } } printf("Yes "); for(i=0;i<n;++i) printf("%lld ",a[i]); }