zoukankan      html  css  js  c++  java
  • [CF165E]Compatible Numbers

    [CF165E]Compatible Numbers

    一.前言

    强忍着调了一下午lemon、疯狂卡常失败的病痛,来水了一道……题目链接

    二.思路

    ​ 这题翻译的很明确了,就直接来。

    ​ 给出的例子是90(1011010)与36(100100)相容,他们&起来等于0.那么简化为 (A&B=0),可以有一个很显然的结论:从 A (B也行)中任意位上取走一个1,得到的 A'&B=0. 十分显然的性质。因为在一位上的两个数&=0,只有两个0和一个1一个0两种情况,很显然取走一个1就是将第一个情况变成第二个。

    ​ 但是此时依旧没有得到和答案有关的结论,没关系。

    ​ 设 ans[i] 为在数列中 &i 为0的,由上面的结论可以得出若 (j|i==0,j<i,ans[j]=ans[i]).那么就可以转移了奥。首先初始化为-1,我们最好选择由大转移到小的。对于一个在数列中的值 k ,求使得 (ans[p]=k),的p的最大值,显而易见的,(p=sim k&inf),(inf为很多个1连在一起,~为按位取反,可以手玩感受一下)

    ​ 那么在读入的时候就计算出 p,然后从inf依次扫描,若 (ans[i]!=-1) 则用 i 对若干个 j(由i取一个1得到)进行转移就好。

    ​ 最后提一点,(inf=(1<<22)-1) ,是因为(log_2(4*10^8)approx22)

    三.CODE

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<fstream>
    #include<cmath>
    #include<cstring>
    using namespace std;
    int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())res=res*10+(ch-'0');
    	return res*f;
    }
    const int inf=(1<<22)-1;
    int n,a[inf+1],ans[inf+1];
    int main(){
    	memset(ans,-1,sizeof(ans));
    	n=read();
    	for(int i=1;i<=n;++i){
    		a[i]=read();
    		ans[~a[i]&inf]=a[i];
    	}
    	for(int i=inf;i>0;--i){
    		if(ans[i]!=-1){
    			for(int j=0;j<=21;++j){
    				if(i&(1<<j)){
    					ans[i-(1<<j)]=ans[i];
    				}
    			}
    		}
    	}
    	for(int i=1;i<=n;++i)cout<<ans[a[i]]<<" ";
    	return 0;
    }
    
  • 相关阅读:
    UVa532 Dungeon Master 三维迷宫
    6.4.2 走迷宫
    UVA 439 Knight Moves
    UVa784 Maze Exploration
    UVa657 The die is cast
    UVa572 Oil Deposits DFS求连通块
    UVa10562 Undraw the Trees
    UVa839 Not so Mobile
    327
    UVa699 The Falling Leaves
  • 原文地址:https://www.cnblogs.com/clockwhite/p/13399274.html
Copyright © 2011-2022 走看看