1. 程式人生 > >牛客練習賽 23 C 托米的位運算

牛客練習賽 23 C 托米的位運算

結束 syn color with bre bsp get class .com

鏈接:https://www.nowcoder.com/acm/contest/156/C
來源:牛客網

托米完成了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, 按原數列的相對順序輸出 (如果行末有額外空格可能會格式錯誤)

輸入

5
1 2 3 4 5

輸出

2
4 5

備註:

n≤ 105, a1... an < 2^31


題意:從n個數中挑出k個數,這k個數組成的序列的值為每個數按位與運算,序列值求出最大的能被2^v整除的數,然後在求出最大的數後要求k的個數也是盡量最大
思路:因為我們是優先求最大的,所以我們貪心取最大的,因為範圍是31次方,所以我們暴力二進制位從高到底,
例如我們要取按位與之後8 我們取所有二進制位包含8的數相與,如果與後等於8了,那麽直接退出,因為是從高到底,肯定算的是最大的值
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int a[N], n, b[N], m;
int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin >> n;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 30; i >= 0; i--) {//從高到低進行枚舉
        m = 0;
        
int s = (1ll << 31) - 1; for(int j = 1; j <= n; j++)//遍歷每個數 if(a[j] >> i & 1) s &= a[j], b[++m] = a[j];//如果找到包含當前二進制位1的就進行與運算,並且把數存下來 // printf("%d %d\n", i, s); if((s & -s) == (1 << i)) break;//判斷最低位是否是二進制位1 } cout << m << endl; bool first = 1; for(int i = 1; i <= m; i++) { if(first) first = 0; else cout << " "; cout << b[i]; } cout << endl; }

牛客練習賽 23 C 托米的位運算