牛客网练习赛23C 托米的位运算题解
题意: 给定n个数, a[1]~a[n], 从中选出k个数 k个数进行与运算的结果为b 使得b%(2^v)==0, 要求v最大, 同时取得的数最多。
思路: 根据二进制的性质可知, 如果我们选中的这些数有一个共同的位(假设该位为第v位)为1即符合b%(2^v)==0, 那么这一位尽量靠前, 则v最大。
所以从大到小枚举二进制位,进行判断即可。 ①枚举的该位为1, ②并且选出的这些数低于这一位的数不全为1 即可。
ps: 如果该位为第v位, 设oth = 2^v - 1 , oth不断与选出的数相与,如果最后oth=0,则符合②这个条件。
最坏时间复杂度: 31 * 1e5 = 3e6
#include <bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; const int N = 1e5+3; int a[N]; vector<int>q; int main() { int n; scanf("%d", &n); for(int i=0;i<n;i++){ scanf("%d", &a[i]); } for(int k=30;k>=0;k--){ int tp = (1<<k), oth = (1<<k)-1; for(int i=0;i<n;i++){ if(tp & a[i]){ oth = oth&a[i]; q.push_back(a[i]); } } if(oth==0) break; } if(q.size()==0){ printf("%d\n", n); for(int i=0;i<n;i++){ printf("%d%c",a[i], i==n-1?'\n':' '); } return 0; } printf("%d\n", q.size()); for(int i=0;i<q.size();i++){ printf("%d%c",q[i],i==q.size()-1?'\n':' '); } return 0; }