给定一个正整数N ,任务是找出从 0 到 N 的所有连续位差异的总和。
注意:如果像 (3, 4) 这样的两个数字的位长不同,则在开头 (011, 100) 附加 0。
例子:
Input: N = 3
Output: 4
Explanation:
Bit differences of (0, 1) + (1, 2) + (2, 3) = 1 + 2 + 1 = 4.
Input: N = 7
Output: 11
天真的方法:
最简单的方法是按位比较范围内的两个连续值,并找出这两个数字相差多少位。将此位差添加到总和中。这样得到的最终和就是所需的解。
时间复杂度: O(N)
方法:
为了优化上述解决方案,需要进行以下观察:
- 数字的连续位差遵循一种模式,即每个等于 (2 i ) 的值 X 与其前一个数字和 X 和 (2 i ) 之上的 (2 i – 1) 个数字有 (i + 1) 位差– 1) X 以下的数字遵循相同的模式。
- 对于 X = 4 (2 2 ),i = 2 的位差为 (2 + 1) 并且数字 (1, 2, 3) 和 (5, 6, 7) 遵循相同的位差模式。
For X = 4, the pattern is as follows:
NUM BIT Diff
1 1(0, 1)
2 2(1, 2)
3 1(2, 3)
4 3(3, 4)
5 1(4, 5)
6 2(5, 6)
7 1(6, 7)
请按照以下步骤解决问题:
- 对于每个N ,找到最近的小于或等于 N 的数字,它是 2 的幂。假设该数字是M 。
- 对于所有小于 M 的数字,可以使用下面的递归方法来找出连续位差的总和。
Count(i) = (i + 1) + 2 * Count(i – 1)
where i is the exponent of the nearest power of 2.
- 初始化一个大小为65(0-based indexing)的数组,存放使用递归函数Count()得到的值,这样以后如果需要Count()相同的值,可以直接获取,不用递归调用Count()函数以节省时间。
- 使用以下公式对大于 M 的剩余数字重复相同的过程。
Sum = Sum + (i+1) + Count(i-1)
例如:
对于 N = 10,使用Count(3)计算最接近的 2 的幂的总和,即 M = 8,然后对大于 8 的剩余数字重复该过程。
下面是上述方法的实现:
C++
// C++ program for the above problem
#include
using namespace std;
long long a[65] = { 0 };
// Recursive function to count
// the sum of bit differences
// of numbers from 1 to
// pow(2, (i+1)) - 1
long long Count(int i)
{
// base cases
if (i == 0)
return 1;
else if (i < 0)
return 0;
// Recursion call if the sum
// of bit difference of numbers
// around i are not calculated
if (a[i] == 0) {
a[i] = (i + 1) + 2 * Count(i - 1);
return a[i];
}
// return the sum of bit
// differences if already
// calculated
else
return a[i];
}
// Function to calculate the
// sum of bit differences up to N
long long solve(long long n)
{
long long i, sum = 0;
while (n > 0) {
// nearest smaller power
// of 2
i = log2(n);
// remaining numbers
n = n - pow(2, i);
// calculate the count
// of bit diff
sum = sum + (i + 1) + Count(i - 1);
}
return sum;
}
// Driver code
int main()
{
long long n = 7;
cout << solve(n) << endl;
return 0;
}
Java
// Java program for the above problem
import java.util.*;
class GFG{
static int a[] = new int[65];
// Recursive function to count
// the sum of bit differences
// of numbers from 1 to
// pow(2, (i+1)) - 1
static int Count(int i)
{
// base cases
if (i == 0)
return 1;
else if (i < 0)
return 0;
// Recursion call if the sum
// of bit difference of numbers
// around i are not calculated
if (a[i] == 0)
{
a[i] = (i + 1) + 2 * Count(i - 1);
return a[i];
}
// return the sum of bit
// differences if already
// calculated
else
return a[i];
}
// Function to calculate the
// sum of bit differences up to N
static int solve(int n)
{
int i, sum = 0;
while (n > 0)
{
// nearest smaller power
// of 2
i = (int)(Math.log(n) / Math.log(2));
// remaining numbers
n = n - (int)Math.pow(2, i);
// calculate the count
// of bit diff
sum = sum + (i + 1) + Count(i - 1);
}
return sum;
}
// Driver code
public static void main(String[] args)
{
int n = 7;
System.out.println(solve(n));
}
}
// This code is contributed by rock_cool
Python3
# Python3 program for the above problem
import math
a = [0] * 65
# Recursive function to count
# the sum of bit differences
# of numbers from 1 to
# pow(2, (i+1)) - 1
def Count(i):
# Base cases
if (i == 0):
return 1
elif (i < 0):
return 0
# Recursion call if the sum
# of bit difference of numbers
# around i are not calculated
if (a[i] == 0):
a[i] = (i + 1) + 2 * Count(i - 1)
return a[i]
# Return the sum of bit
# differences if already
# calculated
else:
return a[i]
# Function to calculate the
# sum of bit differences up to N
def solve(n):
sum = 0
while (n > 0):
# Nearest smaller power
# of 2
i = int(math.log2(n))
# Remaining numbers
n = n - pow(2, i)
# Calculate the count
# of bit diff
sum = sum + (i + 1) + Count(i - 1)
return sum
# Driver code
n = 7
print(solve(n))
# This code is contributed by sanjoy_62
C#
// C# program for the above problem
using System;
class GFG{
static int []a = new int[65];
// Recursive function to count
// the sum of bit differences
// of numbers from 1 to
// pow(2, (i+1)) - 1
static int Count(int i)
{
// base cases
if (i == 0)
return 1;
else if (i < 0)
return 0;
// Recursion call if the sum
// of bit difference of numbers
// around i are not calculated
if (a[i] == 0)
{
a[i] = (i + 1) + 2 * Count(i - 1);
return a[i];
}
// return the sum of bit
// differences if already
// calculated
else
return a[i];
}
// Function to calculate the
// sum of bit differences up to N
static int solve(int n)
{
int i, sum = 0;
while (n > 0)
{
// nearest smaller power
// of 2
i = (int)(Math.Log(n) / Math.Log(2));
// remaining numbers
n = n - (int)Math.Pow(2, i);
// calculate the count
// of bit diff
sum = sum + (i + 1) + Count(i - 1);
}
return sum;
}
// Driver code
public static void Main(String[] args)
{
int n = 7;
Console.Write(solve(n));
}
}
// This code is contributed by shivanisinghss2110
Javascript
输出:
11
时间复杂度: O(log(N))
辅助空间: O(1)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live