Newcoder 156 C.托米的位运算(贪心)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/V5ZSQ/article/details/82917247

Description

托米完成了 1317 1317 的上一个任务,十分高兴,可是考验还没有结束

说话间 1317 1317 给了托米 n n 个自然数 a 1 . . . a n a_1... a_n , 托米可以选出一些带回家,但是他选出的数需要满足一些条件

设托米选出来了$k 个数 b_1,b_2… b_k$, 设这个数列 b b 的给值为 b b 中所有数按位与的结果,如果你能找到一个整除 $b 的最大的 2v , , (v\ge 0)$, 则设定 v v 为这个数列的给价,如果不存在这样的 v v ,则给价值为$ -1$, 1317 1317 希望托米在最大化给价的情况下,最大化$ k$

Input

第一行输入一个整数$ n$, 第二行输入 a 1 . . . a n a_1...a_n

( n 1 0 5 , a 1 , . . . , a n < 2 31 ) (n\le 10^5,a_1,...,a_n<2^{31})

Output

第一行输出最大的整数 k k , 第二行输出 k k 个整数 b 1 . . . b k b_1... b_k , 按原数列的相对顺序输出 (如果行末有额外空格可能会格式错误)

Sample Input

5
1 2 3 4 5

扫描二维码关注公众号,回复: 3494499 查看本文章

Sample Output

2
4 5

Solution

从大到小枚举 v v ,将第 v v 位都为 1 1 的数字取出,若这些数字逻辑与后在第 v v 位后都是 0 0 则说明 v v 合法,此时选取的数字显然最多

Code

#include<cstdio>
using namespace std;
#define maxn 100005
int n,a[maxn],ans[maxn],res;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int v=30;v>=0;v--)
	{
		int temp=(1<<v)-1;
		res=0;
		for(int i=1;i<=n;i++)
			if((a[i]>>v)&1)temp=(temp&a[i]),ans[res++]=i;
		if(temp==0)
		{
			printf("%d\n",res);
			for(int i=0;i<res;i++)printf("%d%c",a[ans[i]],i==res-1?'\n':' ');
			break;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/V5ZSQ/article/details/82917247
156