• 牛客练习赛 23 C 托米的位运算


    链接: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整除的数
    比如10&12=8,所以我们的V是3
    比如5&7=5 所以我们的V是0
    然后在求出最大的数后要求k的个数也是尽量最大,
    思路:因为我们看一个数能被2^v整除,看得还是一个数的最低位是哪个,所以我们取最低位的时候可以使用lowbit,我们又要取最大的那个,那我们就按二进制位1从高到底的去找
    #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
    ", 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;
    }
  • 相关阅读:
    最近很烦心情糟糕透了
    面试心得
    CSS之按钮过滤
    JavaScript之动态背景登陆表单
    VsCode自定义快捷键,一次运行两个或多个Command命令
    Go优化浅谈
    go语言圣经第六章笔记
    go 语言圣经第六章习题
    go 内存对齐
    go语言圣经第五章部分习题
  • 原文地址:https://www.cnblogs.com/Lis-/p/9380451.html
Copyright © 2020-2023  润新知