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

本文介绍了一个有趣的算法问题,旨在通过选择数列中的元素来最大化其特殊给价,同时确保所选元素数量最多。问题要求在给定的数列中找到符合条件的子集,该子集的按位与结果能被最大的2的幂次整除。解决方案通过从高位到低位枚举每一位,检查是否能形成合法的子集,并输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

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

说话间131713171317给了托米 nnn 个自然数 a1...ana_1... a_na1...an, 托米可以选出一些带回家,但是他选出的数需要满足一些条件

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

Input

第一行输入一个整数$ n$, 第二行输入 a1...ana_1...a_na1...an

(n≤105,a1,...,an&lt;231)(n\le 10^5,a_1,...,a_n&lt;2^{31})(n105,a1,...,an<231)

Output

第一行输出最大的整数kkk, 第二行输出kkk 个整数 b1...bkb_1... b_kb1...bk, 按原数列的相对顺序输出 (如果行末有额外空格可能会格式错误)

Sample Input

5
1 2 3 4 5

Sample Output

2
4 5

Solution

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

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值