XOR编程难题建议

XOR programming puzzle advice

本文关键字:难题 编程 XOR      更新时间:2023-10-16

给定一个长intx,计算a满足以下条件的值的数量:

a 异或 x>x
0<a<x

其中ax是长整数,XOR是逐位XOR运算符

你将如何完成这个问题?

我还应该提到,输入x可以大到10^10

我通过在0到x之间迭代来检查条件并增加计数值,从而获得了一个蛮力解决方案。。然而,这不是一个最佳解决方案。。。


这是我尝试过的蛮力。它可以工作,但对于x的大值来说速度非常慢。

for(int i =0; i < x; i++)
{
if((0 < i && i < x) && (i ^ x) > x)
count++;    
}
long long NumberOfA(long long x)
{
long long t = x <<1;
while(t^(t&-t)) t ^= (t&-t);
return t-++x;
}

long long x = 10000000000;
printf("%lld ==> %lldn", 10LL, NumberOfA(10LL) ); 
printf("%lld ==> %lldn", x, NumberOfA(x) ); 

输出

10 ==> 5
10000000000 ==> 7179869183

链接到IDEOne代码


试图解释的逻辑(使用示例10或1010b)

  • 将x向左移动1。(值20或10100b)
  • 关闭所有低位,只保留高位(值16或10000b)
  • 减去x+1(16 - 11 == 5)


试图解释
(尽管这并不容易)

您的规则是a ^ x必须大于x,但不能向ax添加额外的位
(如果以4位值开头,则只能使用4位)

N比特中的数字的最大可能值是2^n -1
(例如,4位数字,2^4-1==15)
让我们把这个数字称为B

在您的值xB(包括)之间,存在B-x的可能值
(回到我的例子,10。在15和10之间,有5个可能的值:1112131415)

在我的代码中,tx << 1,然后关闭所有低位。
(10 << 120;关闭所有低位以获得16)

16 - 1BB-x是您的答案:
(t - 1 - x,t - ++x相同,是答案)

看待这一问题的一种方法是考虑x中的每个位。

  • 如果它是1,那么翻转它将产生一个较小的数字
  • 如果它是0,那么翻转它会产生一个更大的数字,我们应该计算它——以及向右的所有比特组合。这很方便地与掩码值相加
long f(long const x)
{
// only positive x can have non-zero result
if (x <= 0) return 0;
long count = 0;
// Iterate from LSB to MSB
for (long mask = 1;  mask < x;  mask <<= 1)
count += x & mask
? 0
: mask;
return count;
}

我们可能怀疑这里有一个模式——看起来我们只是在复制x并翻转它的比特。

让我们确认一下,使用一个最小的测试程序:

#include <cstdlib>
#include <iostream>
int main(int, char **argv)
{
while (*++argv)
std::cout << *argv << " -> " << f(std::atol(*argv)) << std::endl;
}
0 -> 0
1 -> 0
2 -> 1
3 -> 0
4 -> 3
5 -> 2
6 -> 1
7 -> 0
8 -> 7
9 -> 6
10 -> 5
11 -> 4
12 -> 3
13 -> 2
14 -> 1
15 -> 0

因此,我们所要做的就是"涂抹"该值,以便设置最高有效1之后的所有零位,然后用它进行异或:

long f(long const x)
{
if (x <= 0) return 0;
long mask = x;
while (mask & (mask+1))
mask |= mask+1;
return mask ^ x;
}

这要快得多,而且仍然是O(logn)。