给定三个正整数N 、 X和Y ,任务是计算仅包含X或Y 的N位数字作为数字,并且数字总和也包含X或Y 。由于计数可能非常大,打印计数模10 9 + 7 。
例子:
Input: N = 2, X = 1, Y = 2
Output: 1
Explanation: All possible 2-digit numbers that can be formed using X and Y are 11, 12, 21, 22. Among them, only 11 is a valid number since its sum of digits is 2 (= Y).
Input: N = 3, X = 1, Y = 5
Output: 4
Explanation: All possible 3-digit numbers that can be formed using X and Y are 111, 115, 151, 155. But only 155, 515, 551 and 555 satisfies the given condition. Therefore, the count is 4.
朴素方法:使用递归解决此问题的最简单方法。在每一步,有2 个选择,将数字X或Y放置在当前位置,并在形成的数字的长度等于N时计算数字之和。如果总和也仅由X或Y组成,则计算此数字。检查完所有数字后,打印计数模10 9 + 7 。
时间复杂度: O(2 N )
辅助空间: O(1)
高效方法:上述方法可以通过使用动态规划来优化,因为这个问题同时具有最优子结构和重叠子问题的性质。相同子问题的计算可以通过使用辅助数组dp[N][sum]来存储剩余位数为N且填充位数之和为 sum 时的值。以下是步骤:
- 初始化一个辅助数组dp[][]来存储中间计算。
- 在每一步,有2 个选择将数字X或Y放置在当前位置。
- 当剩余位数为0 时,检查是否可以使用X或Y进行数字总和。如果是,则将当前状态值增加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
Javascript
4
时间复杂度: (N*sum)
辅助空间: O(N*sum)