最后一题 或与加
如果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;