链接:https://www.nowcoder.com/acm/contest/156/C
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
托米完成了1317的上一个任务,十分高兴,可是考验还没有结束
说话间1317给了托米 n 个自然数 a1... an, 托米可以选出一些带回家,但是他选出的数需要满足一些条件
设托米选出来了k 个数 b1,b2... bk, 设这个数列 b 的给值为 b 中所有数按位与的结果,如果你能找到一个整除 b 的最大的 2v,(v≥ 0), 则设定 v 为这个数列的给价,如果不存在这样的 v,则给价值为 -1, 1317 希望托米在最大化给价的情况下,最大化 k
输入描述:
第一行输入一个整数 n, 第二行输入 a1...an
输出描述:
第一行输出最大的整数 k, 第二行输出 k 个整数 b1... bk, 按原数列的相对顺序输出 (如果行末有额外空格可能会格式错误)
示例1
输入
5
1 2 3 4 5
输出
2
4 5
备注:
n≤ 105, a1... an < 231
Description:
在已知序列中选取尽可能多的一些数,使得这些数按位与后的值能整除 2^v(v >= 0) 且尽可能大。
Solution:
假设 a 能整除 2^v,那么也就是说将 a 换成二进制后,有且仅有最高位为1。
由于需要保证v最大,所以可以通过从高位开始枚举,第一个合法解即为答案,那么一个合法解需要满足以下两个条件:
- 当前枚举的 i 位为1;
- 并且选出的这些数(也就是枚举的第 i 位为1),低于这当前 i 位上的的数不全为1。这样就保证了在按位与运算后只有当前的 i 位为1,其他位都为0;
判断一个二进制的某一位是否为1:
假设当前数为X,如果第 i 位为1需要满足:X & (1 << (i - 1)) > 0
判断一个二进制除最高位外其余位是否为0:
假设当前数为X,如果只有最高位为1需要满足:X & ( ( 1 << (i - 1) ) - 1 ) == 0
Code:
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define Fio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fopen freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);
#define mst(a, b) memset(a, b, sizeof(a))
#define _rush() int T; cin >> T; while(T--)
#define rush() int T; scanf("%d", &T); while(T--)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const int Mod = 1e9 + 7;
const int MaxN = 1e5 + 5;
vector <LL> vec;
LL a[MaxN];
int main()
{
Fio;
int n;
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 30; i >= 0; i--) { //从高位开始枚举
int p = 1 << i; //判断当前最高位i是否为1
int pp = p - 1; //判断除最高位外其余位是否为0
for(int j = 1; j <= n; j++) { //遍历整个a数组选取数
if(a[j] & p) { //当前的i位为1
vec.push_back(a[j]);
pp &= a[j];
}
}
if(pp == 0) break; //只有最高位为1,由于是从最高位开始枚举,所以第一个合法解即为答案
vec.clear();
}
cout << vec.size() << endl;
for(int j = 0; j < vec.size(); j++) cout << vec[j] << " ";
cout << endl;
return 0;
}