计数对,最多为 N,总和等于它们的 XOR
给定一个整数N ,任务是计算对(X, Y)的数量,使得X + Y = X ^ Y和X + Y ≤ N 。
注意: ^ 表示按位异或。
例子:
Input: N = 3
Output: 9
Explanation: The pairs satisfying the given conditions are {{0, 0}, {0, 1}, {1, 0}, {0, 2}, {2, 0}, {3, 0}, {0, 3}, {2, 1}, {1, 2}}
Input: N = 10
Output: 37
朴素方法:最简单的方法是生成所有可能的对(X, Y)并检查条件X + Y = X ^ Y和X + Y ≤ N是否满足。
时间复杂度: O(N 2 )
辅助空间: O(1)
有效方法:上述方法可以基于对X和Y的任何值X+Y ≥ X ^ Y的观察进行优化。考虑X和Y的二进制表示。设bit(X, pos)和bit(Y, pos)是在某个固定位置pos对应于X和Y的位。条件X+Y = X^Y只有在 { bit(X, pos), bit(Y, pos)} ∈ {{1, 0}, {0, 1}, {0, 0}}时才会满足。换句话说, X和Y不能在相同的位置设置位。
在有效的方法中,可以使用动态规划来解决问题。这些问题具有重叠的子问题和最优的子结构。子问题使用 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)