📜  从前 X 个自然数生成一个序列,在将 2 提高到最低设置位的幂时,这些自然数相加等于 S

📅  最后修改于: 2021-10-26 06:31:56             🧑  作者: Mango

给定两个整数XS ,任务是构造范围[1, X]中不同整数的序列,使得值2 K的总和等于S ,其中K是第一个设置位的位置每个元素的二进制表示的结尾(基于0的索引)是S

例子:

方法:该问题可以使用贪心方法解决。请按照以下步骤解决问题:

  • 初始化一个变量,比如lowBit,以存储任何数字的2 K值,其中K是从每个元素的二进制表示的末尾开始的第一个设置位的位置。
  • [1, X]范围内所有数字的所有lowBit值插入到V对向量中,以将数字与其lowBit配对lowBit(X)的值可以通过log2(N & -N) + 1 获得
  • 以相反的顺序对向量进行排序以获得最大的lowBit
  • 初始化一个数组,例如ans[] ,以存储所需的集合和一个整数,例如ansSum ,以存储lowBit值的当前总和。
  • 遍历向量V并执行以下步骤:
    • 检查是否(ansSum+v[i].first) <= S ,然后将v[i].second的值添加到数组ans[]并更新ansSum
    • 如果ansSum等于给定的总和S,则中断循环并打印结果数组ans[]作为结果。
  • 如果发现ansSum不等于S,则打印“-1”

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to calculate the lowest
// set bit of any number N
int lowBit(int N)
{
    return log2(N & -N) + 1;
}
 
// Function to generate the sequence
// which adds up to sum on raising 2
// to the power of lowest set bit
// of all integers from the sequence
void find_set(int X, int sum)
{
    // Stores the lowBit value
    vector > v;
 
    // Traverse through 1 to X and
    // insert all the lowBit value
    for (int i = 1; i <= X; i++) {
        pair aux;
        aux.first = lowBit(i);
        aux.second = i;
        v.push_back(aux);
    }
 
    // Sort vector in reverse manner
    sort(v.rbegin(), v.rend());
 
    bool check = false;
 
    // Store all our set values
    vector ans;
 
    // Stores the current
    // summation of lowBit
    int ansSum = 0;
 
    // Traverse vector v
    for (int i = 0; i < v.size(); i++) {
 
        // Check if ansSum+v[i].first
        // is at most sum
        if (ansSum + v[i].first <= sum) {
 
            // Add to the ansSum
            ansSum += v[i].first;
            ans.push_back(v[i].second);
        }
 
        // If ansSum is same as the sum,
        // then break from loop
        if (ansSum == sum) {
            check = true;
            break;
        }
    }
 
    // If check is false, no such
    // sequence can be obtained
    if (!check) {
        cout << "-1";
        return;
    }
 
    // Otherwise, print the sequence
    for (int i = 0; i < ans.size(); i++) {
        cout << ans[i] << " ";
    }
}
 
// Driver Code
int main()
{
    int X = 3, S = 4;
 
    // Generate and print
    // the required sequence
    find_set(X, S);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.util.*;
 
// User defined Pair class
class Pair {
  int x;
  int y;
 
  // Constructor
  public Pair(int x, int y)
  {
    this.x = x;
    this.y = y;
  }
}
 
// class to define user defined conparator
class Compare
{
  static void compare(Pair arr[], int n)
  {
 
    // Comparator to sort the pair according to second element
    Arrays.sort(arr, new Comparator() {
      @Override public int compare(Pair p1, Pair p2)
      {
        return p1.x - p2.x;
      }
    });
  }
}
 
// Driver class
class GFG
{
 
  // Function to calculate the lowest
  // set bit of any number N
  static int lowBit(int N)
  {
    return (int)(Math.log(N & -N) / Math.log(2)) + 1;
  }
 
  // Function to generate the sequence
  // which adds up to sum on raising 2
  // to the power of lowest set bit
  // of all integers from the sequence
  static void find_set(int X, int sum)
  {
    // Stores the lowBit value
    Pair v[] = new Pair[X];
 
    // Traverse through 1 to X and
    // insert all the lowBit value
    for (int i = 0; i < X; i++)
    {
      Pair aux = new Pair(lowBit(i + 1), i + 1);
      v[i] = aux;
    }
 
    // Sort vector in reverse manner
    Compare obj = new Compare();
    obj.compare(v, X);
    int j = X - 1;
    for(int i = 0; i < X / 2; i++)
    {
      Pair temp = v[i];
      v[i] = v[j];
      v[j] = temp;
      j--;
    }
 
    boolean check = false;
 
    // Store all our set values
    Vector ans = new Vector();
 
    // Stores the current
    // summation of lowBit
    int ansSum = 0;
 
    // Traverse vector v
    for (int i = 0; i < X; i++) {
 
      // Check if ansSum+v[i].first
      // is at most sum
      if (ansSum + v[i].x <= sum) {
 
        // Add to the ansSum
        ansSum += v[i].x;
        ans.add(v[i].y);
      }
 
      // If ansSum is same as the sum,
      // then break from loop
      if (ansSum == sum) {
        check = true;
        break;
      }
    }
 
    // If check is false, no such
    // sequence can be obtained
    if (!check)
    {
      System.out.println("-1");
      return;
    }
 
    // Otherwise, print the sequence
    for (int i = 0; i < ans.size(); i++)
    {
      System.out.print(ans.get(i) + " ");
    }
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int X = 3, S = 4;
 
    // Generate and print
    // the required sequence
    find_set(X, S);
  }
}
 
// This code is contributed by divyeshrabadiya07


Python3
# Python3 program for the above approach
from math import log2, ceil, floor
 
# Function to calculate the lowest
# set bit of any number N
def lowBit(N):
     
    return log2(N & -N) + 1
 
# Function to generate the sequence
# which adds up to sum on raising 2
# to the power of lowest set bit
# of all integers from the sequence
def find_set(X, sum):
     
    # Stores the lowBit value
    v = []
 
    # Traverse through 1 to X and
    # insert all the lowBit value
    for i in range(1, X + 1):
        aux = [0, 0]
        aux[0] = lowBit(i)
        aux[1] = i
        v.append(aux)
 
    # Sort vector in reverse manner
    v = sorted(v)[::-1]
 
    check = False
 
    # Store all our set values
    ans = []
 
    # Stores the current
    # summation of lowBit
    ansSum = 0
 
    # Traverse vector v
    for i in range(len(v)):
         
        # Check if ansSum+v[i][0]
        # is at most sum
        if (ansSum + v[i][0] <= sum):
 
            # Add to the ansSum
            ansSum += v[i][0]
            ans.append(v[i][1])
 
        # If ansSum is same as the sum,
        # then break from loop
        if (ansSum == sum):
            check = True
            break
 
    # If check is false, no such
    # sequence can be obtained
    if (not check):
        print("-1")
        return
 
    # Otherwise, print the sequence
    for i in range(len(ans)):
        print(ans[i], end = " ")
 
# Driver Code
if __name__ == '__main__':
     
    X, S = 3, 4
 
    # Generate and pr
    # the required sequence
    find_set(X, S)
 
# This code is contributed by mohit kumar 29


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG {
     
    // Function to calculate the lowest
    // set bit of any number N
    static int lowBit(int N)
    {
        return (int)(Math.Log(N & -N, 2)) + 1;
    }
      
    // Function to generate the sequence
    // which adds up to sum on raising 2
    // to the power of lowest set bit
    // of all integers from the sequence
    static void find_set(int X, int sum)
    {
        // Stores the lowBit value
        List> v = new List>();
      
        // Traverse through 1 to X and
        // insert all the lowBit value
        for (int i = 1; i <= X; i++) {
            Tuple aux = new Tuple(lowBit(i), i);
            v.Add(aux);
        }
      
        // Sort vector in reverse manner
        v.Sort();
        v.Reverse(); 
      
        bool check = false;
      
        // Store all our set values
        List ans = new List();
      
        // Stores the current
        // summation of lowBit
        int ansSum = 0;
      
        // Traverse vector v
        for (int i = 0; i < v.Count; i++) {
      
            // Check if ansSum+v[i].first
            // is at most sum
            if (ansSum + v[i].Item1 <= sum) {
      
                // Add to the ansSum
                ansSum += v[i].Item1;
                ans.Add(v[i].Item2);
            }
      
            // If ansSum is same as the sum,
            // then break from loop
            if (ansSum == sum) {
                check = true;
                break;
            }
        }
      
        // If check is false, no such
        // sequence can be obtained
        if (!check) {
            Console.Write("-1");
            return;
        }
      
        // Otherwise, print the sequence
        for (int i = 0; i < ans.Count; i++) {
            Console.Write(ans[i] + " ");
        }
    }
 
  // Driver code
  static void Main()
  {    
    int X = 3, S = 4;
  
    // Generate and print
    // the required sequence
    find_set(X, S);
  }
}
 
// This code is contributed by divyesh072019


Javascript


输出:
2 3 1

时间复杂度: O(X)
辅助空间: O(X)