📜  给定范围[L,R]中所有元素的XOR

📅  最后修改于: 2021-06-25 12:03:14             🧑  作者: Mango

给定范围[L,R] ,任务是查找给定范围内所有整数的XOR,即(L)^(L + 1)^(L + 2)^…^(R)
例子:

一个简单的解决方案是从LR迭代查找所有数字的XOR。这将花费线性时间。
更好的解决方案是首先找到整数R中的最高有效位。我们的答案不能比“ R”大得多。对于介于0和MSB(含)之间的每个位“ i”,我们将尝试确定L和R(含)之间的整数个数的奇偶校验,以使“ i”位被设置。如果计数为奇数,则还将设置最终答案的i位。
现在真正的问题是,对于第一个问题,我们如何确定计数的奇偶性?
首先,让我们看一下前16个整数的二进制表示形式。

很容易注意到,第i位的状态在每2个i数之后发生变化。我们将使用这个想法来预测一些整数的计数与第i位设置范围从左至右的包容性。
这里有两种情况:

  1. 情况1(i!= 0):我们尝试确定是否设置了L的i位。如果已设置,我们将尝试查找L和L + 2 i(含)之间的数量计数的奇偶性,以使它们的i位被设置。如果L的i位被置位且L为奇数,则此计数将为奇数,否则为偶数。
    类似地,对于R,我们尝试确定R – 2 i和R之间的多个元素的计数的奇偶性,从而设置它们的i位。如果L的i位被设置且L为偶数,则此计数将为奇数,否则为偶数。
    我们忽略它们之间的所有其他整数,因为它们将具有偶数设置了i位的整数。
  2. 情况2(i = 0):在这里,我们有以下情况:
    • 如果L和R均为奇数,则设置0位的整数的计数为(R – L)/ 2 + 1
    • 在任何其他情况下,计数将为floor((R – L + 1)/ 2)

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
 
// Function to return the
// most significant bit
int msb(int x)
{
    int ret = 0;
    while ((x >> (ret + 1)) != 0)
        ret++;
    return ret;
}
 
// Function to return the required XOR
int xorRange(int l, int r)
{
 
    // Finding the MSB
    int max_bit = msb(r);
 
    // Value of the current bit to be added
    int mul = 2;
 
    // To store the final answer
    int ans = 0;
 
    // Loop for case 1
    for (int i = 1; i <= max_bit; i++) {
 
        // Edge case when both the integers
        // lie in the same segment of continuous
        // 1s
        if ((l / mul) * mul == (r / mul) * mul) {
            if (((l & (1 << i)) != 0) && (r - l + 1) % 2 == 1)
                ans += mul;
            mul *= 2;
            continue;
        }
 
        // To store whether parity of count is odd
        bool odd_c = 0;
 
        if (((l & (1 << i)) != 0) && l % 2 == 1)
            odd_c = (odd_c ^ 1);
        if (((r & (1 << i)) != 0) && r % 2 == 0)
            odd_c = (odd_c ^ 1);
 
        // Updating the answer if parity is odd
        if (odd_c)
            ans += mul;
 
        // Updating the number to be added
        mul *= 2;
    }
 
    // Case 2
    int zero_bit_cnt = zero_bit_cnt = (r - l + 1) / 2;
 
    if (l % 2 == 1 && r % 2 == 1)
        zero_bit_cnt++;
 
    if (zero_bit_cnt % 2 == 1)
        ans++;
 
    return ans;
}
 
// Driver code
int main()
{
    int l = 1, r = 4;
 
    // Final answer
    cout << xorRange(l, r);
 
    return 0;
}


Java
// Java implementation of the approach
class GFG
{
     
// Function to return the
// most significant bit
static int msb(int x)
{
    int ret = 0;
    while ((x >> (ret + 1)) != 0)
        ret++;
    return ret;
}
 
// Function to return the required XOR
static int xorRange(int l, int r)
{
 
    // Finding the MSB
    int max_bit = msb(r);
 
    // Value of the current bit to be added
    int mul = 2;
 
    // To store the final answer
    int ans = 0;
 
    // Loop for case 1
    for (int i = 1; i <= max_bit; i++)
    {
 
        // Edge case when both the integers
        // lie in the same segment of continuous
        // 1s
        if ((l / mul) * mul == (r / mul) * mul)
        {
            if (((l & (1 << i)) != 0) && (r - l + 1) % 2 == 1)
                ans += mul;
            mul *= 2;
            continue;
        }
 
        // To store whether parity of count is odd
        int odd_c = 0;
 
        if (((l & (1 << i)) != 0) && l % 2 == 1)
            odd_c = (odd_c ^ 1);
        if (((r & (1 << i)) != 0) && r % 2 == 0)
            odd_c = (odd_c ^ 1);
 
        // Updating the answer if parity is odd
        if (odd_c!=0)
            ans += mul;
 
        // Updating the number to be added
        mul *= 2;
    }
 
    // Case 2
    int zero_bit_cnt = zero_bit_cnt = (r - l + 1) / 2;
 
    if (l % 2 == 1 && r % 2 == 1)
        zero_bit_cnt++;
 
    if (zero_bit_cnt % 2 == 1)
        ans++;
 
    return ans;
}
 
// Driver code
public static void main(String args[])
{
    int l = 1, r = 4;
 
    // Final answer
    System.out.print(xorRange(l, r));
}
}
 
// This code is contributed by Arnab Kundu


Python3
# Python3 implementation of the approach
 
# Function to return the most significant bit
def msb(x) :
 
    ret = 0
    while ((x >> (ret + 1)) != 0) :
        ret = ret + 1
    return ret
 
# Function to return the required XOR
def xorRange(l, r) :
 
    # Finding the MSB
    max_bit = msb(r)
 
    # Value of the current bit to be added
    mul = 2
 
    # To store the final answer
    ans = 0
 
    # Loop for case 1
    for i in range (1, max_bit + 1) :
 
        # Edge case when both the integers
        # lie in the same segment of continuous
        # 1s
        if ((l // mul) * mul == (r // mul) * mul) :
            if ((((l & (1 << i)) != 0) and
                 (r - l + 1) % 2 == 1)) :
                ans = ans + mul
            mul = mul * 2
            continue
         
        # To store whether parity of count is odd
        odd_c = 0
 
        if (((l & (1 << i)) != 0) and l % 2 == 1) :
            odd_c = (odd_c ^ 1)
        if (((r & (1 << i)) != 0) and r % 2 == 0) :
            odd_c = (odd_c ^ 1)
 
        # Updating the answer if parity is odd
        if (odd_c) :
            ans = ans + mul
 
        # Updating the number to be added
        mul = mul * 2
     
    # Case 2
    zero_bit_cnt = (r - l + 1) // 2
 
    if ((l % 2 == 1 ) and (r % 2 == 1)) :
        zero_bit_cnt = zero_bit_cnt + 1
 
    if (zero_bit_cnt % 2 == 1):
        ans = ans + 1
 
    return ans
 
# Driver code
l = 1
r = 4
 
# Final answer
print(xorRange(l, r))
 
# This code is contributed by ihritik


C#
// C# implementation of the approach
using System;
 
class GFG
{
     
// Function to return the
// most significant bit
static int msb(int x)
{
    int ret = 0;
    while ((x >> (ret + 1)) != 0)
        ret++;
    return ret;
}
 
// Function to return the required XOR
static int xorRange(int l, int r)
{
 
    // Finding the MSB
    int max_bit = msb(r);
 
    // Value of the current bit to be added
    int mul = 2;
 
    // To store the final answer
    int ans = 0;
 
    // Loop for case 1
    for (int i = 1; i <= max_bit; i++)
    {
 
        // Edge case when both the integers
        // lie in the same segment of continuous
        // 1s
        if ((l / mul) * mul == (r / mul) * mul)
        {
            if (((l & (1 << i)) != 0) && (r - l + 1) % 2 == 1)
                ans += mul;
            mul *= 2;
            continue;
        }
 
        // To store whether parity of count is odd
        int odd_c = 0;
 
        if (((l & (1 << i)) != 0) && l % 2 == 1)
            odd_c = (odd_c ^ 1);
        if (((r & (1 << i)) != 0) && r % 2 == 0)
            odd_c = (odd_c ^ 1);
 
        // Updating the answer if parity is odd
        if (odd_c!=0)
            ans += mul;
 
        // Updating the number to be added
        mul *= 2;
    }
 
    // Case 2
    int zero_bit_cnt = zero_bit_cnt = (r - l + 1) / 2;
 
    if (l % 2 == 1 && r % 2 == 1)
        zero_bit_cnt++;
 
    if (zero_bit_cnt % 2 == 1)
        ans++;
 
    return ans;
}
 
// Driver code
public static void Main(String []args)
{
    int l = 1, r = 4;
 
    // Final answer
    Console.Write(xorRange(l, r));
}
}
 
// This code contributed by Rajput-Ji


PHP
> ($ret + 1)) != 0)
        $ret++;
    return $ret;
}
 
// Function to return the required XOR
function xorRange($l, $r)
{
 
    // Finding the MSB
    $max_bit = msb($r);
 
    // Value of the current bit to be added
    $mul = 2;
 
    // To store the final answer
    $ans = 0;
 
    // Loop for case 1
    for ($i = 1; $i <= $max_bit; $i++)
    {
 
        // Edge case when both the integers
        // lie in the same segment of continuous
        // 1s
        if ((int)(($l / $mul) * $mul) ==
            (int)(($r / $mul) * $mul))
        {
            if ((($l & (1 << $i)) != 0) &&
                 ($r - $l + 1) % 2 == 1)
                $ans += $mul;
            $mul *= 2;
            continue;
        }
 
        // To store whether parity of count is odd
        $odd_c = 0;
 
        if ((($l & (1 << $i)) != 0) && $l % 2 == 1)
            $odd_c = ($odd_c ^ 1);
        if ((($r & (1 << $i)) != 0) && $r % 2 == 0)
            $odd_c = ($odd_c ^ 1);
 
        // Updating the answer if parity is odd
        if ($odd_c)
            $ans += $mul;
 
        // Updating the number to be added
        $mul *= 2;
    }
 
    // Case 2
    $zero_bit_cnt = (int)(($r - $l + 1) / 2);
 
    if ($l % 2 == 1 && $r % 2 == 1)
        $zero_bit_cnt++;
 
    if ($zero_bit_cnt % 2 == 1)
        $ans++;
 
    return $ans;
}
 
// Driver code
$l = 1;
$r = 4;
 
// Final answer
echo xorRange($l, $r);
 
// This code is contributed by mits
?>


Javascript


C++
// C++ implementation of the approach
#include 
using namespace std;
 
// Function to return the required XOR
long computeXOR(const int n)
{
    // Modulus operator are expensive
    // on most of the computers.
    // n & 3 will be equivalent to n % 4
    // n % 4
    switch (n & 3) {
 
    // If n is a multiple of 4
    case 0:
        return n;
 
    // If n % 4 gives remainder 1
    case 1:
        return 1;
 
    // If n % 4 gives remainder 2
    case 2:
        return n + 1;
 
    // If n % 4 gives remainder 3
    case 3:
        return 0;
    }
}
 
// Driver code
int main()
{
    int l = 1, r = 4;
    cout << (computeXOR(r) ^ computeXOR(l - 1));
 
    return 0;
}


Java
// Java implementation of the approach
class GFG
{
     
// Function to return the required XOR
static long computeXOR(int n)
{
    // Modulus operator are expensive
    // on most of the computers.
    // n & 3 will be equivalent to n % 4
    // n % 4
    int x = n & 3;
    switch (x)
    {
 
        // If n is a multiple of 4
        case 0:
            return n;
     
        // If n % 4 gives remainder 1
        case 1:
            return 1;
     
        // If n % 4 gives remainder 2
        case 2:
            return n + 1;
     
        // If n % 4 gives remainder 3
        case 3:
            return 0;
    }
    return 0;
}
 
// Driver code
public static void main(String args[])
{
    int l = 1, r = 4;
    System.out.println(computeXOR(r) ^
                       computeXOR(l - 1));
}
}
 
// This code is contributed by Ryuga


Python3
# Python3 implementation of the approach
 
# Function to return the required XOR
def computeXOR(n) :
 
    # Modulus operator are expensive
    # on most of the computers.
    # n & 3 will be equivalent to n % 4
    # n % 4
    switch = {
 
        # If n is a multiple of 4
        0 : n,
 
        # If n % 4 gives remainder 1
        1 : 1,
 
        # If n % 4 gives remainder 2
        2: n + 1,
 
        # If n % 4 gives remainder 3
        3 : 0,
    }
    return switch.get( n & 3, "")
 
# Driver code
l = 1
r = 4
print(computeXOR(r) ^ computeXOR(l - 1))
 
# This code is contributed by ihritik


C#
// C# implementation of the approach
using System;
class GFG
{
     
// Function to return the required XOR
static long computeXOR(int n)
{
    // Modulus operator are expensive
    // on most of the computers.
    // n & 3 will be equivalent to n % 4
    // n % 4
    int x=n&3;
    switch (x)
    {
 
    // If n is a multiple of 4
    case 0:
        return n;
 
    // If n % 4 gives remainder 1
    case 1:
        return 1;
 
    // If n % 4 gives remainder 2
    case 2:
        return n + 1;
 
    // If n % 4 gives remainder 3
    case 3:
        return 0;
    }
    return 0;
}
 
// Driver code
static void Main()
{
    int l = 1, r = 4;
    Console.WriteLine(computeXOR(r) ^ computeXOR(l - 1));
}
}
 
// This code is contributed by mits


PHP


Javascript


输出:
4

时间复杂度: O(log 2 (R))
高效的方法:令F(N)为计算所有小于或等于N的自然数的XOR的函数。因此,对于范围(LR),答案将为F(R)^ F(L-1)
如本文所述,可以在O(1)中找到任意给定数字的该函数的值。
下面是上述方法的实现:

C++

// C++ implementation of the approach
#include 
using namespace std;
 
// Function to return the required XOR
long computeXOR(const int n)
{
    // Modulus operator are expensive
    // on most of the computers.
    // n & 3 will be equivalent to n % 4
    // n % 4
    switch (n & 3) {
 
    // If n is a multiple of 4
    case 0:
        return n;
 
    // If n % 4 gives remainder 1
    case 1:
        return 1;
 
    // If n % 4 gives remainder 2
    case 2:
        return n + 1;
 
    // If n % 4 gives remainder 3
    case 3:
        return 0;
    }
}
 
// Driver code
int main()
{
    int l = 1, r = 4;
    cout << (computeXOR(r) ^ computeXOR(l - 1));
 
    return 0;
}

Java

// Java implementation of the approach
class GFG
{
     
// Function to return the required XOR
static long computeXOR(int n)
{
    // Modulus operator are expensive
    // on most of the computers.
    // n & 3 will be equivalent to n % 4
    // n % 4
    int x = n & 3;
    switch (x)
    {
 
        // If n is a multiple of 4
        case 0:
            return n;
     
        // If n % 4 gives remainder 1
        case 1:
            return 1;
     
        // If n % 4 gives remainder 2
        case 2:
            return n + 1;
     
        // If n % 4 gives remainder 3
        case 3:
            return 0;
    }
    return 0;
}
 
// Driver code
public static void main(String args[])
{
    int l = 1, r = 4;
    System.out.println(computeXOR(r) ^
                       computeXOR(l - 1));
}
}
 
// This code is contributed by Ryuga

Python3

# Python3 implementation of the approach
 
# Function to return the required XOR
def computeXOR(n) :
 
    # Modulus operator are expensive
    # on most of the computers.
    # n & 3 will be equivalent to n % 4
    # n % 4
    switch = {
 
        # If n is a multiple of 4
        0 : n,
 
        # If n % 4 gives remainder 1
        1 : 1,
 
        # If n % 4 gives remainder 2
        2: n + 1,
 
        # If n % 4 gives remainder 3
        3 : 0,
    }
    return switch.get( n & 3, "")
 
# Driver code
l = 1
r = 4
print(computeXOR(r) ^ computeXOR(l - 1))
 
# This code is contributed by ihritik

C#

// C# implementation of the approach
using System;
class GFG
{
     
// Function to return the required XOR
static long computeXOR(int n)
{
    // Modulus operator are expensive
    // on most of the computers.
    // n & 3 will be equivalent to n % 4
    // n % 4
    int x=n&3;
    switch (x)
    {
 
    // If n is a multiple of 4
    case 0:
        return n;
 
    // If n % 4 gives remainder 1
    case 1:
        return 1;
 
    // If n % 4 gives remainder 2
    case 2:
        return n + 1;
 
    // If n % 4 gives remainder 3
    case 3:
        return 0;
    }
    return 0;
}
 
// Driver code
static void Main()
{
    int l = 1, r = 4;
    Console.WriteLine(computeXOR(r) ^ computeXOR(l - 1));
}
}
 
// This code is contributed by mits

的PHP


Java脚本


输出:
4