题意:1-n-1个数和1-n-1个数两两匹配,每次匹配将两个数的值进行与运算,要求每次匹配与运算的和相加最小,问满足匹配的配对方式
分析:打表前10个数与运算最小的匹配,我们发现,从n-1开始按位取反可以得到前面的一个值,这两个值的与运算结果为0
不管奇数还是偶数,前面和后面的数都可以两两匹配,偶数刚好匹配,奇数还剩下一个0,0可以与0匹配结果还是0
AC代码:
#include <map> #include <set> #include <stack> #include <cmath> #include <queue> #include <cstdio> #include <vector> #include <string> #include <bitset> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> #define ls (r<<1) #define rs (r<<1|1) #define debug(a) cout << #a << " " << a << endl using namespace std; typedef long long ll; const ll maxn = 1e6+10; const ll mod = 1e9+7; const double pi = acos(-1.0); const double eps = 1e-8; ll vis[maxn], a[maxn]; ll f( ll x ) { string t = ""; while(x) { char c = (x%2)+'0'; t += c; x /= 2; } ll sum = 0; for( ll i = t.length()-1; i >= 0; i -- ) { ll tmp = t[i]-'0'; sum = sum*2 + !tmp; } //debug(sum); return sum; } int main() { ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); //f(1); f(2); f(3); ll n; while( cin >> n ) { memset(vis,0,sizeof(vis)); memset(a,0,sizeof(a)); for( ll i = n-1; i >= 0; i -- ) { //debug(i); if( i == 0 && !vis[i] ) { a[i] = 0; continue; } if( !vis[i] ) { a[i] = f(i); //debug(f(i)); vis[f(i)] = i; } else { a[i] = vis[i]; } } for( ll i = 0; i < n; i ++ ) { if( i == n-1 ) { cout << a[i] << endl; } else { cout << a[i] << " "; } } } return 0; }