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

📅  最后修改于: 2021-04-26 19:20:35             🧑  作者: Mango

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

例子:

一个简单的解决方案是从LR迭代查找所有数字的XOR。这将花费线性时间。

更好的解决方案是首先找到整数R中的最高有效位。我们的答案的最高有效位不能大于“ R”的最高有效位。对于介于0和MSB(含)之间的每个位“ i”,我们将尝试确定L和R(含)之间的整数计数的奇偶校验,以便设置“ ith ”位。如果计数为奇数,则还将设置最终答案的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)

    对于情况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
?>


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


输出:
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


输出:
4