📌  相关文章
📜  计算由X或Y组成的N位数字,其数字总和也由X或Y组成

📅  最后修改于: 2021-04-24 21:01:23             🧑  作者: Mango

给定三个正整数NXY ,任务是将仅包含XY的N位数字计数为数字,并且数字总和还包含XY。由于计数可能非常大,请以10 9 + 7为模数打印计数。

例子:

天真的方法:使用递归解决此问题的最简单方法。在每个步骤中,有2个选择,将数字XY放置在当前位置,并在形成的数字的长度等于N时计算数字的总和。如果总和也仅由XY构成,则计数此数字。检查所有数字后,以10 9 + 7为模数打印计数。

时间复杂度: O(2 N )
辅助空间: O(1)

高效方法:由于此问题同时具有最优子结构重叠子问题的属性,因此可以通过使用动态规划来优化上述方法。相同的子问题的计算可以通过使用辅助阵列DP [N] [总和]存储的值时的左数字的数目是N和填充位数之和的总和来避免。步骤如下:

  • 初始化辅助数组dp [] []以存储中间计算。
  • 在每个步骤中,有2个选择可将数字XY放置在当前位置。
  • 当剩余位数为0时,检查是否可以使用XY进行位数求和。如果是,则将当前状态值加1
  • 否则将当前状态更新为0
  • 如果遇到相同的子问题,则以模数10 9 + 7返回已经计算的值。
  • 将数字X和数字Y放在当前位置,然后递归到其余位置,并在每一步传递数字总和。
  • 对于每个对值x和y的递归调用,将当前状态更新为这些状态返回的值之和。
  • 完成上述步骤后,打印dp [N] [0]的值作为结果计数。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Stores the value of overlapping
// states
int dp[1000 + 5][9000 + 5];
int mod = 1000000007;
 
// Function to check whether a number
// have only digits X or Y or not
int check(int sum, int x, int y)
{
    // Until sum is positive
    while (sum > 0) {
 
        int ln = sum % 10;
 
        // If any digit is not
        // X or Y then return 0
        if (ln != x && ln != y) {
            return 0;
        }
        sum /= 10;
    }
 
    // Return 1
    return 1;
}
 
// Function to find the count of
// numbers that are formed by digits
// X and Y and whose sum of digit
// also have digit X or Y
int countNumbers(int n, int x, int y, int sum)
{
    // Initialize dp array
    memset(dp, -1, sizeof(dp));
 
    // Base Case
    if (n == 0) {
 
        // Check if sum of digits
        // formed by only X or Y
        return check(sum, x, y);
    }
 
    // Return the already computed
    if (dp[n][sum] != -1) {
        return dp[n][sum] % mod;
    }
 
    // Place the digit X at the
    // current position
    int option1 = countNumbers(n - 1, x,
                               y, sum + x) % mod;
 
    // Place the digit Y at the
    // current position
    int option2 = countNumbers(n - 1, x,
                               y, sum + y) % mod;
 
    // Update current state result
    return dp[n][sum] = (option1 + option2) % mod;
}
 
// Driver Code
int main()
{
    int N = 3, X = 1, Y = 5;
 
    // Function Call
    cout << countNumbers(N, X, Y, 0) % mod;
    // This code is contributed by bolliranadheer
}


Java
// Java program for the above approach
 
import java.util.*;
public class Main {
 
    // Stores the value of overlapping
    // states
    static int dp[][] = new int[1000 + 5][9000 + 5];
    static int mod = 1000000007;
 
    // Function to find the count of
    // numbers that are formed by digits
    // X and Y and whose sum of digit
    // also have digit X or Y
    public static int countNumbers(int n, int x, int y,
                                   int sum)
    {
        // Initialize dp array
        for (int i[] : dp)
            Arrays.fill(i, -1);
 
        // Base Case
        if (n == 0) {
 
            // Check if sum of digits
            // formed by only X or Y
            return check(sum, x, y);
        }
 
        // Return the already computed
        if (dp[n][sum] != -1) {
            return dp[n][sum] % mod;
        }
 
        // Place the digit X at the
        // current position
        int option1
            = countNumbers(n - 1, x, y, sum + x) % mod;
 
        // Place the digit Y at the
        // current position
        int option2
            = countNumbers(n - 1, x, y, sum + y) % mod;
 
        // Update current state result
        return dp[n][sum] = (option1 + option2) % mod;
    }
 
    // Function to check whether a number
    // have only digits X or Y or not
    public static int check(int sum, int x, int y)
    {
        // Until sum is positive
        while (sum > 0) {
 
            int ln = sum % 10;
 
            // If any digit is not
            // X or Y then return 0
            if (ln != x && ln != y) {
                return 0;
            }
            sum /= 10;
        }
 
        // Return 1
        return 1;
    }
 
    // Driver Code
    public static void main(String args[])
    {
        int N = 3, X = 1, Y = 5;
 
        // Function Call
        System.out.println(countNumbers(N, X, Y, 0) % mod);
    }
}


Python3
# Python3 program for the above approach
 
# Stores the value of overlapping
# states
dp = [[-1 for x in range(9000 + 5)]
          for y in range(1000 + 5)]
mod = 1000000007
 
# Function to check whether a number
# have only digits X or Y or not
def check(sum, x, y):
 
    # Until sum is positive
    while (sum > 0):
        ln = sum % 10
 
        # If any digit is not
        # X or Y then return 0
        if (ln != x and ln != y):
            return 0
 
        sum //= 10
 
    # Return 1
    return 1
 
# Function to find the count of
# numbers that are formed by digits
# X and Y and whose sum of digit
# also have digit X or Y
def countNumbers(n, x, y, sum):
 
    # Initialize dp array
    global dp
 
    # Base Case
    if (n == 0):
 
        # Check if sum of digits
        # formed by only X or Y
        return check(sum, x, y)
 
    # Return the already computed
    if (dp[n][sum] != -1):
        return dp[n][sum] % mod
 
    # Place the digit X at the
    # current position
    option1 = countNumbers(n - 1, x,
                      y, sum + x) % mod
 
    # Place the digit Y at the
    # current position
    option2 = countNumbers(n - 1, x,
                      y, sum + y) % mod
 
    # Update current state result
    dp[n][sum] = (option1 + option2) % mod
     
    return dp[n][sum]
 
# Driver Code
if __name__ == "__main__":
     
    N = 3
    X = 1
    Y = 5
 
    # Function Call
    print(countNumbers(N, X, Y, 0) % mod)
 
# This code is contributed by chitranayal


C#
// C# program for the above approach
using System;
 
class GFG{
 
// Stores the value of overlapping
// states
static int [,]dp = new int[100 + 5, 900 + 5];
static int mod = 10000007;
 
// Function to find the count of
// numbers that are formed by digits
// X and Y and whose sum of digit
// also have digit X or Y
public static int countNumbers(int n, int x,
                               int y, int sum)
{
     
    // Initialize dp array
    for(int i = 0; i < dp.GetLength(0); i++)
    {
        for(int j = 0; j < dp.GetLength(1); j++)
        {
            dp[i, j] = -1;
        }
    }
     
    // Base Case
    if (n == 0)
    {
         
        // Check if sum of digits
        // formed by only X or Y
        return check(sum, x, y);
    }
     
    // Return the already computed
    if (dp[n, sum] != -1)
    {
        return dp[n, sum] % mod;
    }
 
    // Place the digit X at the
    // current position
    int option1 = countNumbers(n - 1, x, y,
                             sum + x) % mod;
 
    // Place the digit Y at the
    // current position
    int option2 = countNumbers(n - 1, x, y,
                             sum + y) % mod;
 
    // Update current state result
    return dp[n,sum] = (option1 + option2) % mod;
}
 
// Function to check whether a number
// have only digits X or Y or not
public static int check(int sum, int x, int y)
{
     
    // Until sum is positive
    while (sum > 0)
    {
        int ln = sum % 10;
 
        // If any digit is not
        // X or Y then return 0
        if (ln != x && ln != y)
        {
            return 0;
        }
        sum /= 10;
    }
 
    // Return 1
    return 1;
}
 
// Driver Code
public static void Main(String []args)
{
    int N = 3, X = 1, Y = 5;
 
    // Function Call
    Console.WriteLine(countNumbers(
        N, X, Y, 0) % mod);
}
}
 
// This code is contributed by Princi Singh


输出
4







时间复杂度: (N * sum)
辅助空间: O(N * sum)