CodeForces165E 位运算 贪心 + 状压dp

http://codeforces.com/problemset/problem/165/E

题意 

两个整数 x 和 y 是 兼容的,如果它们的位运算 "AND" 结果等于 0,亦即 a b = 0 。例如,数 90 (10110102) 和 36 (1001002) 是兼容的,因为 10110102 1001002 = 02;而数 (112)和 (1102) 是不兼容的,因为 112 1102 = 102 。

给定一个整数数组 a1, a2, ..., an 。您的任务是判断每个数组元素:这个元素是否与给定数组中的某个其它元素兼容?如果问题的答案是肯定的,则应找出任意一个匹配的元素。

第一眼觉得用01字典树可做,但当所有值都是1的时候,每次遍历就要遍历整个字典树,很显然会T。只能考虑其他做法。

我们发现给的数据范围是400w,是可以直接用数组开下的,考虑到&运算的时候只有原数字位位1和另一个数字相同位为1的时候才会导致不匹配。

所以我们利用贪心的思想,先把能与这个数匹配的最大数直接存入数组,之后从后往前遍历,如果遇到没有匹配的数字,就考虑比他多一位1的数字有没有匹配,因为在相同位上1总为0的子集,因此这样预处理之后可直接输出,

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
const double eps = 1e-9;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,tmp,K;
int dp[1 << 23]; 
int a[maxn];
int main()
{
    Sca(N);
    For(i,1,N){
        int x; Sca(x); a[i] = x;
        dp[x ^ ((1 << 23) - 1)] = x;
    }
    for(int i = (1 << 23) - 1; i >= 0 ; i --){
        if(!dp[i]){
            for(int j = 0; j < 23; j ++){
                if(dp[i | (1 << j)]){
                    dp[i] = dp[i | (1 << j)];
                    break;
                }
            }
        }
    }
    For(i,1,N){
        if(dp[a[i]]) printf("%d ",dp[a[i]]);
        else printf("-1 ");
    }
    #ifdef VSCode
    system("pause");
    #endif
    return 0;
}
原文地址:https://www.cnblogs.com/Hugh-Locke/p/9629955.html