有多少组4个数字,它们的xor等于0?

时间:2017-04-04 05:49:00

标签: algorithm dynamic-programming combinatorics xor bitwise-xor

我有两个非负整数x和y,它们都有最多30位(所以它们的值大约是10 ^ 9)。

我想计算有多少组4个数字{a_1,a_2,a_3,a_4},a_1 + a_2 = x和a_3 + a_4 = y,所有这4个数字的xor等于0 。

解决此问题的最快算法是什么?

我能想到的最快的是将xor方程重新排列为a_1 xor a_2 = a_3 xor a_4。

然后我可以计算O(x)中左侧的所有值和O(y)中右侧的值,因此整个算法以O(x + y)运行。

1 个答案:

答案 0 :(得分:4)

N(x, y)成为此问题的解决方案的数量。显然N(0, 0)是1,因为唯一的解是(0,0,0,0)。如果xy为负数,那么就没有解决方案,因为我们要求a1,a2,a3,a4都是非负数。

否则,我们可以通过求解最低位来进行,并生成递归关系。让我们写n:0n:1来表示2n + 0和2n + 1(所以0和1是最低位)。

然后:

N(0, 0) = 1
N(-x, y) = N(x, -y) = 0
N(x:0, y:0) = N(x, y) + N(x-1, y) + N(x, y-1) + N(x-1, y-1)
N(x:0, y:1) = N(x:1, y:0) = 0
N(x:1, y:1) = 4 * N(x, y)

要看到这些,必须考虑任何a1,a2,a3,a4的可能低位。

首先N(x:0, y:0)。我们需要a1 + a2的低位为0,这意味着a1和a2都是偶数,或者它们都是奇数。如果它们都是奇数,那么进位和高位加1的总和必须与x的高位相加。同样的逻辑适用于a3,a4。有4种可能性:a1,a2,a3,a4的所有底部位为0,a1,a2的底部位为1,a3的底部位,a4为1,a1,a2,a3,a4的底部位是那个案例。

其次是N(x:0, y:1)N(x:1, y:0)。如果一个和是偶数而另一个是奇数,则没有解决方案:可以检查a1,a2,a3,a4的最低位的每个组合以找出。

第三N(x:1, y:1)。 a1和a2中的一个必须是奇数,并且类似地,a3和a4中的一个必须是奇数。这有四种可能性,在任何情况下都没有随身携带。

这是一个完整的解决方案:

def N(x, y):
    if x == y == 0: return 1
    if x < 0 or y < 0: return 0
    if x % 2 == y % 2 == 0:
        return N(x//2, y//2) + N(x//2-1, y//2) + N(x//2, y//2-1) + N(x//2-1, y//2-1)
    elif x % 2 == y % 2 == 1:
        return 4 * N(x//2, y//2)
    else:
        return 0

该算法进行了几次递归调用,因此理论上是指数式的。但实际上许多分支都很快终止,因此代码运行速度足够快,最高可达2 ^ 30。但是,当然,您可以添加缓存或使用动态编程表来保证O(log(x)+ log(y))的运行时。

最后,为了增加对正确性的信心,这里有一些针对天真O(xy)解决方案的测试:

def N_slow(x, y):
    s = 0
    for a1 in xrange(x + 1):
        for a3 in xrange(y + 1):
            a2 = x - a1
            a4 = y - a3
            if a1 ^ a2 ^ a3 ^ a4:
                continue
            s += 1
    return s

for x in xrange(50):
    for y in xrange(50):
        n = N(x, y)
        ns = N_slow(x, y)
        if n != ns:
            print 'N(%d, %d) = %d, want %d' % (x, y, n, ns)