题意:给一个数 n,让你求一个排列,使得这个排列与0-n的对应数的异或之最大。
析:既然是异或就得考虑异或的用法,然后想怎么才是最大呢,如果两个数二进制数正好互补,不就最大了么,比如,一个数是100,那么我们只要找11,(都是二进制)
这不就正好么,一试,果然是这样。就是这样找,而且两两正好配对,如果多了一个就是0呗,也就是0.那知道一个数,怎么找那另一个和它互补的呢?其实很简单,
就是用111-100=11,就是利用这个,就能很轻松把这个题解决,注意可能超int,要用long long。
代码如下:
#include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <set> #include <queue> #include <string> #include <algorithm> #include <vector> #include <map> using namespace std ; typedef long long LL; const int maxn = 1e6 + 5; const int INF = 0x3f3f3f3f; int ans[maxn]; int main(){ int n; cin >> n; memset(ans, -1, sizeof(ans)); LL sum = 0; for(int i = n; i >= 0; --i){ if(ans[i] > -1) continue; for(int j = 0; ; ++j){ if((1 << j)-1 >= i){ int t = (1<<j) - 1; ans[i] = t - i; ans[t-i] = i; sum += ((1<<j)-1) << 1; break; } } } cout << sum << endl; for(int i = 0; i <= n; ++i) if(!i) printf("%d", ans[i]); else printf(" %d", ans[i]); printf(" "); return 0; }