📜  前 N 个非负整数的连续位差之和

📅  最后修改于: 2021-09-08 12:48:04             🧑  作者: Mango

给定一个正整数N ,任务是找出从 0 到 N 的所有连续位差异的总和。
注意:如果像 (3, 4) 这样的两个数字的位长不同,则在开头 (011, 100) 附加 0。
例子:

天真的方法:
最简单的方法是按位比较范围内的两个连续值,并找出这两个数字相差多少位。将此位差添加到总和中。这样得到的最终和就是所需的解。
时间复杂度: 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 的数字,可以使用下面的递归方法来找出连续位差的总和。
  • 初始化一个大小为65(0-based indexing)的数组,存放使用递归函数Count()得到的值,这样以后如果需要Count()相同的值,可以直接获取,不用递归调用Count()函数以节省时间。
  • 使用以下公式对大于 M 的剩余数字重复相同的过程。

例如:
对于 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