[CF165E]Compatible Numbers
Posted clockwhite
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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;
}
以上是关于[CF165E]Compatible Numbers的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces - 165E Compatible Numbers(SOSdp)
$题解 CF110A Nearly Lucky Number$