托米的位运算
链接:https://ac.nowcoder.com/acm/problem/16762
来源:牛客网
题目描述
托米完成了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
//看的大佬题解,大佬牛逼
//解释看代码注释
//https://ac.nowcoder.com/acm/problem/16762 //满足题意的b,在二进制中,有一位共同位都是1,然后这位数后边的应当不全为1, //不全为1时,&一下后变就变为0,也就不会产生余数,也就能整除了 //此题要求b%2的v次=0; #include<bits/stdc++.h> #define ll long long using namespace std; const int N=1e5+100; #define ll long long int a[N],s[N]; typedef pair<int,int> PII; //typedef pair<int,int>PII; vector<int>q; int n,l,r; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>n; for(int i=0;i<n;i++) cin>>a[i]; for(int i=31;i>=0;i--) { q.clear();//记得每次判断后清空 int v=(1<<i),t=(1<<i)-1;//v也就是题中2的v次,在二进制中,只有一位是1 //左移31位,是int是32位,也就是最顶点变成1了 //t是用来判断自己所找的数中,v位后边的不全为0 for(int k=0;k<n;k++) //t中是第v位后边全为1,如果找的b里边低于v的某位 { //全为1,则t最后不等于0 if(a[k]&v) q.push_back(a[k]),t=t&a[k]; } if(t==0) break;//找到则break,这是最大的v } cout<<q.size()<<endl; for(int i=0;i<q.size()-1;i++) { cout<<q[i]<<" "; } cout<<q[q.size()-1]; return 0; > }