📌  相关文章
📜  计数对,最多为 N,总和等于它们的 XOR

📅  最后修改于: 2022-05-13 01:56:04.951000             🧑  作者: Mango

计数对,最多为 N,总和等于它们的 XOR

给定一个整数N ,任务是计算对(X, Y)的数量,使得X + Y = X ^ YX + Y ≤ N
注意: ^ 表示按位异或

例子:

朴素方法:最简单的方法是生成所有可能的对(X, Y)并检查条件X + Y = X ^ YX + Y ≤ N是否满足。

时间复杂度: O(N 2 )
辅助空间: O(1)

有效方法:上述方法可以基于对XY的任何值X+Y ≥ X ^ Y的观察进行优化。考虑XY的二进制表示。设bit(X, pos)bit(Y, pos)是在某个固定位置pos对应于XY的位。条件X+Y = X^Y只有在 { bit(X, pos), bit(Y, pos)} ∈ {{1, 0}, {0, 1}, {0, 0}}时才会满足。换句话说, XY不能在相同的位置设置位。

在有效的方法中,可以使用动态规划来解决问题。这些问题具有重叠的子问题和最优的子结构。子问题使用 memoization 存储在dp[][] 表中,其中dp[i][bound]存储从第 i个位置到末尾的答案,并且bound是一个布尔变量,以确保数字的总和不超过N。

  • 将极限N转换为其 二进制表示。将二进制表示形式存储在字符串中,例如S ,以便仅在字符串的长度上迭代而不是实际限制就足够了。
  • 通过执行以下步骤定义递归函数IsSumEqualsXor(i, bound)
    • 检查基本情况,如果i == length of S然后返回 1 ,因为已形成有效对。
    • 如果已经计算了状态 dp[i][bound ]的结果,则返回状态dp[i][bound]
    • 在当前位置i ,可以通过检查几个条件来分配{{0, 0}, {0, 1}, {1, 0}}中的三个对中的任何一个。他们是
      • 如果边界S中的当前字符即S[i]'0'则只有{0, 0}可以 作为有效对放置在当前位置。这样做是为了确保总和不超过N
      • 否则,可以放置{{0, 0}, {0, 1}, {1, 0}}之间的任何对,并将绑定相应地设置为 true 或 false。
    • 在当前位置放置一个有效对后,为索引(i + 1)处的元素递归调用IsSumEqualsXor函数。
    • 返回所有可能的有效数字位置的总和作为答案。

以下是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// 2D array for memoization
int dp[1000][2];
 
// Recursive Function to count pairs
// (x, y) such that x+y = x^y
int IsSumEqualsXor(int i, int n,
                   bool bound, string& s)
{
    // If the string is traversed completely
    if (i == n)
        return 1;
 
    // If the current subproblem
    // is already calculated
    if (dp[i][bound] != -1)
        return dp[i][bound];
 
    int ans = 0;
 
    // If bound = 1 and  s[i] == '0',
    // only (0, 0) can be placed
    if (bound and s[i] == '0') {
        ans = IsSumEqualsXor(i + 1, n, 1, s);
    }
 
    // Otherwise
    else {
        // Placing (0, 1) and (1, 0) are
        // equivalent. Hence, multiply by 2.
        ans = 2
              * IsSumEqualsXor(i + 1, n,
                               bound & (s[i] == '1'), s);
 
        // Place (0, 0) at the current position.
        ans += IsSumEqualsXor(i + 1, n, 0, s);
    }
 
    // Return the answer
    return dp[i][bound] = ans;
}
 
// Utility Function to convert N
// to its binary representation
string convertToBinary(int n)
{
    string ans;
    while (n) {
 
        char rem = char(n % 2 + '0');
        ans.push_back(rem);
        n /= 2;
    }
    reverse(ans.begin(), ans.end());
    return ans;
}
 
// Function to count pairs (x, y)
// such that x + y = x^y
void IsSumEqualsXorUtil(int N)
{
    // Convert the number to
    // equivalent binary representation
    string s = convertToBinary(N);
 
    // Initialize dp array with -1.
    memset(dp, -1, sizeof dp);
 
    // Print answer returned by recursive function
    cout << IsSumEqualsXor(0, s.size(), 1, s) << endl;
}
 
// Driver code
int main()
{
    // Input
    int N = 10;
 
    // Function call
    IsSumEqualsXorUtil(N);
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// 2D array for memoization
static int [][]dp = new int[1000][2];
 
// Recursive Function to count pairs
// (x, y) such that x+y = x^y
static int IsSumEqualsXor(int i, int n,
                   int bound, char[] s)
{
    // If the String is traversed completely
    if (i == n)
        return 1;
 
    // If the current subproblem
    // is already calculated
    if (dp[i][bound] != -1)
        return dp[i][bound];
 
    int ans = 0;
 
    // If bound = 1 and  s[i] == '0',
    // only (0, 0) can be placed
    if (bound!=0 && s[i] == '0') {
        ans = IsSumEqualsXor(i + 1, n, 1, s);
    }
 
    // Otherwise
    else {
        // Placing (0, 1) and (1, 0) are
        // equivalent. Hence, multiply by 2.
        ans = 2
              * IsSumEqualsXor(i + 1, n,
                               bound!=0 & (s[i] == '1')?1:0, s);
 
        // Place (0, 0) at the current position.
        ans += IsSumEqualsXor(i + 1, n, 0, s);
    }
 
    // Return the answer
    return dp[i][bound] = ans;
}
static String reverse(String input) {
    char[] a = input.toCharArray();
    int l, r = a.length - 1;
    for (l = 0; l < r; l++, r--) {
        char temp = a[l];
        a[l] = a[r];
        a[r] = temp;
    }
    return String.valueOf(a);
}
// Utility Function to convert N
// to its binary representation
static String convertToBinary(int n)
{
    String ans="";
    while (n>0) {
 
        char rem = (char)(n % 2 + '0');
        ans+=(rem);
        n /= 2;
    }
    ans = reverse(ans);
    return ans;
}
 
// Function to count pairs (x, y)
// such that x + y = x^y
static void IsSumEqualsXorUtil(int N)
{
    // Convert the number to
    // equivalent binary representation
    String s = convertToBinary(N);
 
    // Initialize dp array with -1.
    for(int i = 0; i < dp.length; i++)
    {
        for (int j = 0; j < dp[0].length; j++) {
            dp[i][j] = -1;
        }
    }
 
    // Print answer returned by recursive function
    System.out.print(IsSumEqualsXor(0, s.length(), 1, s.toCharArray()) +"\n");
}
 
// Driver code
public static void main(String[] args)
{
    // Input
    int N = 10;
 
    // Function call
    IsSumEqualsXorUtil(N);
}
}
 
// This code is contributed by shikhasingrajput


Python3
# Python3 program for the above approach
 
# 2D array for memoization
dp = [[-1 for i in range(2)]
          for j in range(1000)]
 
# Recursive Function to count pairs
# (x, y) such that x+y = x^y
def IsSumEqualsXor(i, n, bound, s):
     
    # If the string is traversed completely
    if (i == n):
        return 1
 
    # If the current subproblem
    # is already calculated
    if (dp[i][bound] != -1):
        return dp[i][bound]
 
    ans = 0
 
    # If bound = 1 and  s[i] == '0',
    # only (0, 0) can be placed
    if (bound and s[i] == '0'):
        ans = IsSumEqualsXor(i + 1, n, 1, s)
 
    # Otherwise
    else:
         
        # Placing (0, 1) and (1, 0) are
        # equivalent. Hence, multiply by 2.
        ans = 2 * IsSumEqualsXor(
            i + 1, n, bound & (s[i] == '1'), s)
 
        # Place (0, 0) at the current position.
        ans += IsSumEqualsXor(i + 1, n, 0, s)
         
    dp[i][bound] = ans
 
    # Return the answer
    return ans
 
# Utility Function to convert N
# to its binary representation
def convertToBinary(n):
     
    ans = []
     
    while (n):
        rem = chr(n % 2 + 48)
        ans.append(rem)
        n //= 2
         
    ans = ans[::-1]
    return ans
 
# Function to count pairs (x, y)
# such that x + y = x^y
def IsSumEqualsXorUtil(N):
     
    # Convert the number to
    # equivalent binary representation
    s = convertToBinary(N)
 
    # Print answer returned by recursive function
    print(IsSumEqualsXor(0, len(s), 1, s))
 
# Driver code
if __name__ == '__main__':
     
    # Input
    N = 10
     
    # Function call
    IsSumEqualsXorUtil(N)
     
# This code is contributed by ipg2016107


C#
// C# program for the above approach
using System;
 
class GFG{
 
// 2D array for memoization
static int [,]dp = new int[1000, 2];
 
// Recursive Function to count pairs
// (x, y) such that x+y = x^y
static int IsSumEqualsXor(int i, int n,
                          int bound, char[] s)
{
     
    // If the String is traversed completely
    if (i == n)
        return 1;
 
    // If the current subproblem
    // is already calculated
    if (dp[i,bound] != -1)
        return dp[i,bound];
 
    int ans = 0;
 
    // If bound = 1 and  s[i] == '0',
    // only (0, 0) can be placed
    if (bound != 0 && s[i] == '0')
    {
        ans = IsSumEqualsXor(i + 1, n, 1, s);
    }
 
    // Otherwise
    else
    {
         
        // Placing (0, 1) and (1, 0) are
        // equivalent. Hence, multiply by 2.
        ans = 2 * IsSumEqualsXor(i + 1, n,
                                 bound != 0 &
                                 (s[i] == '1') ? 1 : 0, s);
 
        // Place (0, 0) at the current position.
        ans += IsSumEqualsXor(i + 1, n, 0, s);
    }
 
    // Return the answer
    return dp[i, bound] = ans;
}
 
static String reverse(String input)
{
    char[] a = input.ToCharArray();
    int l, r = a.Length - 1;
     
    for(l = 0; l < r; l++, r--)
    {
        char temp = a[l];
        a[l] = a[r];
        a[r] = temp;
    }
    return String.Join("", a);
}
 
// Utility Function to convert N
// to its binary representation
static String convertToBinary(int n)
{
    String ans = "";
    while (n > 0)
    {
        char rem = (char)(n % 2 + '0');
        ans += (rem);
        n /= 2;
    }
    ans = reverse(ans);
    return ans;
}
 
// Function to count pairs (x, y)
// such that x + y = x^y
static void IsSumEqualsXorUtil(int N)
{
     
    // Convert the number to
    // equivalent binary representation
    String s = convertToBinary(N);
 
    // Initialize dp array with -1.
    for(int i = 0; i < dp.GetLength(0); i++)
    {
        for(int j = 0; j < dp.GetLength(1); j++)
        {
            dp[i, j] = -1;
        }
    }
 
    // Print answer returned by recursive function
    Console.Write(IsSumEqualsXor(0, s.Length, 1,
                                 s.ToCharArray()) +"\n");
}
 
// Driver code
public static void Main(String[] args)
{
     
    // Input
    int N = 10;
 
    // Function call
    IsSumEqualsXorUtil(N);
}
}
 
// This code is contributed by umadevi9616


Javascript


输出:
37

时间复杂度: O(Log 2 N)
辅助空间: O(Log 2 N)