牛客《今日头条》笔试题

最后一题 或与加

如果x+y=x|y 表示x y满足或与加

要求,输入两个数x,k,输出 第k小的y;

示例 输入 5 1

输出2,由于 5+1!=5|1 ,因此第一小的数为2

分析:显然满足x+y=x|y的数,有部分0 1互补的特点,也就是只有在x(y)为0的比特位置,y(x)才能为1,不然相加是必然产生进位。因此(x&y==0)成立

第k小,其实就是在x为0的位置进行二进制计数,

比如100100011,第一小的数 100100111

第二小的数相加后的结果100101011

第三小的数相加后的结果100101111

第八小的数相加后的结果111100011

因此第k小数y,也就是100101111^100100011了。

代码

#include <iostream>
#include <vector>
using namespace std;
int main(){
    unsigned long long x, k, y;
    vector<unsigned long long> pos1;
    unsigned long long ans = 0;
    while (cin >> x >> k)
    unsigned long long *aa = &x;
    {
        pos1.clear();
        for (unsigned long long i = 0; i < 64; i++)
        {
            if ((x&1) == 0)
            {
                pos1.push_back(i);
            }
            x >>= 1;
        }
        ans = 0;
        unsigned long long ind = 0;
        while (k)
        {
            unsigned long long a = pos1[ind++];
            unsigned long long b = k & 1;
            k >>= 1;
            ans = ans | (b << a);
        }
        cout << (ans) << endl;
    }
}

有大神写的更简洁些

        while (x){
            long long low = (tmp - 1)&k;
            long long high = k - low;
            if (x & 1){
                high <<= 1;
            }
            k = high + low;
            tmp <<= 1;
            x >>= 1;

        }
        cout << k << endl;
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值