📌  相关文章
📜  将N转换为最小可能值

📅  最后修改于: 2021-05-07 06:29:54             🧑  作者: Mango

给定两个数字, ND。将以下两个操作中的任何一个应用于N

  1. D加到N
  2. 改变Ndigitsum(N),其中digitsum(N)N个数字的总和

任务是将N转换为最小可能值。打印最小可能值N和应用给定操作的次数(其中任何一个)。操作次数必须最少。

例子:

先决条件:
1.给定大整数的数字根(重复的数字和)
2.具有给定数字根的范围内的数字

方法 :
令Dr(x)是为整数x定义的函数,如下所示:

  • 如果0 <= x <= 9 ,则Dr(x) = x
  • 否则, Dr(x) = Dr(Sum-of-digits(x))

函数Dr(x)是数字x的数字根。

  • Dr(a+b) = Dr(Dr(a) + Dr(b))
  • Dr(ab) = Dr(Dr(a) * Dr(b))

重要观察:对于某些非负整数k,最小值始终是: Dr(N + kD)的最小值。

Dr(N + kD) = Dr(Dr(N) + Dr(kD))          (1)

现在, Dr(kd) = Dr(Dr(k) * Dr(D))
Dr(k)的可能值为0、1、2…9,由数字k = 0、1、2…9给出

Dr(x) = Dr(Sum-of-digits(x))             (2)
  • N的最小值等于数字总和(N)的最小值。如果我们减少一次此答案并加上D,则可获得的最小值将保持不变。因此,如果需要先执行reduce操作再执行add操作,那么我们可以先执行add操作再执行reduce操作,而不会影响可能达到的根。从公式(1)和(2)的组合可以明显看出这一点。
  • 因此,我们可以先执行所有加法运算,然后再进行所有归约运算,并达到任何一组操作可能达到的任何数量。使用以上权利要求,我们可以证明最小可能值是Dr(N + kD)的最小值,其中0 <= k <= 9
  • 要查找最小步骤数,请注意加法和位数求和操作的相对顺序确实会影响答案。另外,请注意,“数字和”函数的降低非常快。
  • <= 10的任何数字10等于<= 90的数字,任何<= 90的数字<= 18表示的数字,依此类推。简而言之,任何数字都可以以<= 5的步数减少到其数字根。
  • 通过这一点,我们可以证明最小步长的值永远不会大于15。这是一个宽松的上限,而不是确切的上限。
  • 使用蛮力递归算法,该算法在每个步骤都沿2个不同的方向分支,一个x = Sum-of-digits(x) ,另一个为x = x+D ,但是直到递归深度为15为止。我们将在探索2种15种不同的方式后停下来。

下面是上述方法的实现:

C++
// CPP program to transform N to the minimum value
#include 
using namespace std;
  
// Intialising the answer
int min_val = INT_MAX;
int min_steps = 0;
  
// Function to find the digitsum
int sumOfDigits(int n)
{
    string s = to_string(n);
  
    int sum = 0;
  
    // Iterate over all digits and add them
    for (int i = 0; i < s.length(); i++) {
        sum += (s[i] - '0');
    }
      
    // Return the digit su,
    return sum;
}
  
// Function to transform N to the minimum value
void Transform(int n, int d, int steps)
{
    // If the final value is lesser than least value
    if (n < min_val) {
        min_val = n;
        min_steps = steps;
    }
  
    // If final value is equal to least value then check 
    // for lesser number of steps to reach this value
    else if (n == min_val) {
        min_steps = min(min_steps, steps);
    }
  
    // The value will be obtained in less than 15 steps as 
    // proved so applying normal recursive operations
    if (steps < 15) {
        Transform(sumOfDigits(n), d, steps + 1);
        Transform(n + d, d, steps + 1);
    }
}
  
// Driver code
int main()
{
    int N = 9, D = 3;
      
    // Function call
    Transform(N, D, 0);
      
    // Print the answers
    cout << min_val << " " << min_steps;
      
    return 0;
}


Java
// JAVA program to transform N to the minimum value
import java.util.*;
  
class GFG{
   
// Intialising the answer
static int min_val = Integer.MAX_VALUE;
static int min_steps = 0;
   
// Function to find the digitsum
static int sumOfDigits(int n)
{
    String s = String.valueOf(n);
   
    int sum = 0;
   
    // Iterate over all digits and add them
    for (int i = 0; i < s.length(); i++) {
        sum += (s.charAt(i) - '0');
    }
       
    // Return the digit su,
    return sum;
}
   
// Function to transform N to the minimum value
static void Transform(int n, int d, int steps)
{
    // If the final value is lesser than least value
    if (n < min_val) {
        min_val = n;
        min_steps = steps;
    }
   
    // If final value is equal to least value then check 
    // for lesser number of steps to reach this value
    else if (n == min_val) {
        min_steps = Math.min(min_steps, steps);
    }
   
    // The value will be obtained in less than 15 steps as 
    // proved so applying normal recursive operations
    if (steps < 15) {
        Transform(sumOfDigits(n), d, steps + 1);
        Transform(n + d, d, steps + 1);
    }
}
   
// Driver code
public static void main(String[] args)
{
    int N = 9, D = 3;
       
    // Function call
    Transform(N, D, 0);
       
    // Print the answers
    System.out.print(min_val+ " " +  min_steps);
       
}
}
  
// This code is contributed by 29AjayKumar


Python3
# Python3 program to transform N to the minimum value
import sys;
  
# Intialising the answer
min_val = sys.maxsize;
min_steps = 0;
  
# Function to find the digitsum
def sumOfDigits(n) :
  
    s = str(n);
  
    sum = 0;
  
    # Iterate over all digits and add them
    for i in range(len(s)) :
        sum += (ord(s[i]) - ord('0'));
      
    # Return the digit su,
    return sum;
  
# Function to transform N to the minimum value
def Transform(n, d, steps) :
    global min_val;global min_steps;
      
    # If the final value is lesser than least value
    if (n < min_val) :
        min_val = n;
        min_steps = steps;
  
    # If final value is equal to least value then check 
    # for lesser number of steps to reach this value
    elif (n == min_val) :
        min_steps = min(min_steps, steps);
      
    # The value will be obtained in less than 15 steps as 
    # proved so applying normal recursive operations
    if (steps < 15) :
        Transform(sumOfDigits(n), d, steps + 1);
        Transform(n + d, d, steps + 1);
  
# Driver code
if __name__ == "__main__" :
  
    N = 9; D = 3;
      
    # Function call
    Transform(N, D, 0);
      
    # Print the answers
    print(min_val, min_steps);
      
# This code is contributed by Yash_R


C#
// C# program to transform N to the minimum value
using System;
  
class GFG{
   
// Intialising the answer
static int min_val = int.MaxValue;
static int min_steps = 0;
   
// Function to find the digitsum
static int sumOfDigits(int n)
{
    string s = n.ToString(); 
   
    int sum = 0;
   
    // Iterate over all digits and add them
    for (int i = 0; i < s.Length; i++) {
        sum += (s[i] - '0');
    }
       
    // Return the digit su,
    return sum;
}
   
// Function to transform N to the minimum value
static void Transform(int n, int d, int steps)
{
    // If the final value is lesser than least value
    if (n < min_val) {
        min_val = n;
        min_steps = steps;
    }
   
    // If final value is equal to least value then check 
    // for lesser number of steps to reach this value
    else if (n == min_val) {
        min_steps = Math.Min(min_steps, steps);
    }
   
    // The value will be obtained in less than 15 steps as 
    // proved so applying normal recursive operations
    if (steps < 15) {
        Transform(sumOfDigits(n), d, steps + 1);
        Transform(n + d, d, steps + 1);
    }
}
   
// Driver code
public static void Main(string[] args)
{
    int N = 9, D = 3;
       
    // Function call
    Transform(N, D, 0);
       
    // Print the answers
    Console.Write(min_val+ " " +  min_steps); 
}
}
  
// This code is contributed by Yash_R


输出:
3 2

时间复杂度: O(T \cdot 2^{15} \cdot log_{10} N )