Question link ~~>
Question recognition:It is really a good question. I thought for a long time during the competition. I thought that enumeration would change the 0 of a certain digit to 1, but every number would not time out, at that time, I did not expect it to be okay to enumerate from large to small.
Solution:
This question requires two numbers A & B = 0. If a = 10010, B must at least (that is, 1 in a must be 0) be 01101, or 00101,000 01, 00000. It is equivalent to making your request (must satisfy) when you go shopping. It does not matter in other aspects. In this way, we can enumerate 1 in B and change it to 0. How can we enumerate it? One enumeration is not acceptable, and it definitely times out. We can enumerate it in a unified way, just like the state compression and update status, which is equivalent to recursion and optimize it with the idea of dynamic planning, each number can only change to 0, and then change with the changed number.
Code:
#include<iostream>#include<sstream>#include<map>#include<cmath>#include<fstream>#include<queue>#include<vector>#include<sstream>#include<cstring>#include<cstdio>#include<stack>#include<bitset>#include<ctime>#include<string>#include<cctype>#include<iomanip>#include<algorithm>using namespace std ;#define INT __int64#define L(x) (x * 2)#define R(x) (x * 2 + 1)const int INF = 0x3f3f3f3f ;const double esp = 0.0000000001 ; const double PI = acos(-1.0) ;const INT mod = 1e9 + 7 ;const int MY = 15 ;const int MX = (1<<22) + 5 ;int n ;int dp[MX] ,g[MX] ;int main(){ //freopen("input.txt" ,"r" ,stdin) ; while(~scanf("%d" ,&n)) { int S = (1<<22) - 1 ; memset(dp ,0 ,sizeof(dp)) ; for(int i = 0 ;i < n ; ++i) { scanf("%d" ,&g[i]) ; dp[g[i]^S] = g[i] ; // g[I] 需要的另一半 } for(int i = S ; i >= 0 ; --i) // 枚举各种状态 { if(!dp[i]) // 如果没有存值 { for(int j = 0 ;j < 22 ; ++j) // 给其添加 1 让其变成有值 if(dp[i|(1<<j)]) dp[i] = dp[i|(1<<j)] ; } } for(int i = 0 ;i < n ; ++i) { if(i) cout<<" " ; if(dp[g[i]]) cout<<dp[g[i]] ; else cout<<"-1" ; } cout<<endl ; } return 0 ;}
Codeforces 164 e compatible numbers