cf CodeForces - 165E 【状压dp】



题意:


        给你n个数,相互按位且运算, 输出a1-an。

       满足num[i]&a[i]==0; a[i]属于num。 没有满足的输出-1。



题解:

       

        没个数最大4e6 也就是1<<22,所以最大的数为N=1<<22-1。

        a&(a^N)==0;

        dp[i] 表示状态i & dp[i]==0;

        所以输入直接可以dp[num[i]^N]=num[i];

        然后从N->0的状态,逆推过来,考虑添加任何一位不会影响结果,所以每一位加一遍。

       dp[stat]=dp[stat|(1<<i)];



#include<bits/stdc++.h>

#define ll long long
using namespace std;
const int N=(1<<22)-1;
const int maxn=1e6+10;
int dp[(1<<23)+10];
int num[maxn];
int main(){
    int n,x;
    scanf("%d",&n);
    for(int i=0;i<n;++i){
        scanf("%d",&num[i]);
        dp[num[i]^N]=num[i];
    }
    for(int stat=N;stat>=0;--stat)if(!dp[stat]){
        for(int i=0;i<23;++i)if(dp[stat|(1<<i)]){
            dp[stat]=dp[stat|(1<<i)];
        }
    }
    for(int i=0;i<n;++i){
        if(dp[num[i]])
            printf("%d ",dp[num[i]]);
        else
            printf("%d ",-1);
    }
    puts("");
    return 0;
}



      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值