码迷,mamicode.com
首页 > 其他好文 > 详细

[CF165E]Compatible Numbers

时间:2020-07-29 21:45:39      阅读:62      评论:0      收藏:0      [点我收藏+]

标签:span   pre   lang   例子   problem   line   main   没有   最大值   

[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

标签:span   pre   lang   例子   problem   line   main   没有   最大值   

原文地址:https://www.cnblogs.com/clockwhite/p/13399274.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!