给定三个正整数L , R和Y ,任务是计算数字总和等于Y的[L,R]范围内的数字
例子:
Input: L = 500, R = 1000, Y = 6
Output: 3
Explanation:
Numbers in the range [500, 600] whose sum of digits is Y(= 6) are:
501 = 5 + 0 + 1 = 6
510 = 5 + 1 + 0 = 6
600 = 6 + 0 + 0 = 6
Therefore, the required output is 3.
Input: L = 20, R = 10000, Y = 14
Output: 540
天真的方法:请参阅上一篇文章,通过遍历[L,R]范围内的所有数字来解决此问题,并对每个数字检查其数字总和是否等于Y。如果发现为真,则增加计数。最后,打印获得的计数。
时间复杂度: O(R – L +1)* log 10 (R)
辅助空间: O(1)
高效的方法:为了优化上述方法,我们的想法是通过以下递归关系使用Digit DP:
where, sum: Represents sum of digits.
tight: Check if sum of digits exceed Y or not.
end: Stores the maximum possible value of ith digit of a number.
cntNum(N, Y, tight): Returns the count of numbers in the range [0, X] whose sum of digits is Y.
请按照以下步骤解决问题:
- 初始化3D数组dp [N] [Y] [tight],以计算和存储上述递归关系的所有子问题的值。
- 最后,返回dp [N] [sum] [tight]的值。
下面是上述方法的实现:
C++
// CPP program for the above approach
#include
using namespace std;
#define M 1000
// Function to find the sum of digits
// of numbers in the range [0, X]
int cntNum(string X, int i, int sum,
int tight, int dp[M][M][2])
{
// Check if count of digits in a number
// greater than count of digits in X
if (i >= X.length() || sum < 0) {
// If sum of digits of a
// number is equal to Y
if (sum == 0) {
return 1;
}
return 0;
}
// Check if current subproblem has
// already been computed
if (dp[sum][i][tight] != -1) {
return dp[sum][i][tight];
}
// Stores count of numbers whose
// sum of digits is Y
int res = 0;
// Check if the number
// exceeds Y or not
int end = tight ? X[i] - '0' : 9;
// Iterate over all possible
// values of i-th digits
for (int j = 0; j <= end; j++) {
// Update res
res += cntNum(X, i + 1, sum - j,
(tight & (j == end)), dp);
}
// Return res
return dp[sum][i][tight]=res;
}
// Utility function to count the numbers in
// the range [L, R] whose sum of digits is Y
int UtilCntNumRange(int L, int R, int Y)
{
// Base Case
if (R == 0 && Y == 0) {
return 1;
}
// Stores numbers in the form
// of its equivalent string
string str = to_string(R);
// Stores overlapping subproblems
int dp[M][M][2];
// Initialize dp[][][]
memset(dp, -1, sizeof(dp));
// Stores count of numbers
// in the range [0, R]
int cntR = cntNum(str, 0, Y,
true, dp);
// Update str
str = to_string(L - 1);
// Initialize dp[][][]
memset(dp, -1, sizeof(dp));
// Stores count of numbers in
// the range [0, L - 1]
int cntL = cntNum(str, 0, Y,
true, dp);
return (cntR - cntL);
}
// Driver Code
int main()
{
int L = 20, R = 10000, Y = 14;
cout << UtilCntNumRange(L, R, Y);
}
Java
// Java program for the above approach
import java.util.*;
class GFG{
static final int M = 1000;
// Function to find the sum of digits
// of numbers in the range [0, X]
static int cntNum(String X, int i, int sum,
int tight, int dp[][][])
{
// Check if count of digits in a number
// greater than count of digits in X
if (i >= X.length() || sum < 0) {
// Check Iif sum of digits of a
// number is equal to Y
if (sum == 0) {
return 1;
}
return 0;
}
// Check if current subproblem has
// already been computed
if (dp[sum][i][tight] != -1) {
return dp[sum][i][tight];
}
// Stores count of numbers whose
// sum of digits is Y
int res = 0;
// Check if the number
// exceeds Y or not
int end = tight != 0 ? X.charAt(i) - '0' : 9;
// Iterate over all possible
// values of i-th digits
for (int j = 0; j <= end; j++) {
// Update res
res += cntNum(X, i + 1, sum - j,
(tight > 0 & (j == end)) ==
true ? 1 : 0, dp);
}
// Return res
return dp[sum][i][tight]=res;
}
// Utility function to count the numbers in
// the range [L, R] whose sum of digits is Y
static int UtilCntNumRange(int L, int R, int Y)
{
// Base Case
if (R == 0 && Y == 0) {
return 1;
}
// Stores numbers in the form
// of its equivalent String
String str = String.valueOf(R);
// Stores overlapping subproblems
int [][][]dp = new int[M][M][2];
// Initialize dp[][][]
for(int i = 0; i < M; i++)
{
for (int j = 0; j < M; j++) {
for (int k = 0; k < 2; k++)
dp[i][j][k] = -1;
}
}
// Stores count of numbers
// in the range [0, R]
int cntR = cntNum(str, 0, Y,
1, dp);
// Update str
str = String.valueOf(L - 1);
// Initialize dp[][][]
for(int i = 0; i < M; i++)
{
for (int j = 0; j < M; j++) {
for (int k = 0; k < 2; k++)
dp[i][j][k] = -1;
}
}
// Stores count of numbers in
// the range [0, L - 1]
int cntL = cntNum(str, 0, Y,
1, dp);
return (cntR - cntL);
}
// Driver Code
public static void main(String[] args)
{
int L = 20, R = 10000, Y = 14;
System.out.print(UtilCntNumRange(L, R, Y));
}
}
// This code is contributed by shikhasingrajput
Python3
# Python program for the above approach
M = 1000
# Function to find the sum of digits
# of numbers in the range [0, X]
def cntNum(X, i, sum, tight, dp):
# Check if count of digits in a number
# greater than count of digits in X
if (i >= len(X) or sum < 0):
# Check if sum of digits of a
# number is equal to Y
if (sum == 0):
return 1
return 0
# Check if current subproblem has
# already been comrputed
if (dp[sum][i][tight] != -1):
return dp[sum][i][tight]
# Stores count of numbers whose
# sum of digits is Y
res, end = 0, 9
# Check if the number
# exceeds Y or not
if tight:
end = ord(X[i]) - ord('0')
# end = tight ? X[i] - '0' : 9;
# Iterate over all possible
# values of i-th digits
for j in range(end + 1):
# Update res
res += cntNum(X, i + 1, sum - j,
(tight & (j == end)), dp)
# Return res
dp[sum][i][tight] = res
return res
# Utility function to count the numbers in
# the range [L, R] whose sum of digits is Y
def UtilCntNumRange(L, R, Y):
# Base Case
if (R == 0 and Y == 0):
return 1
# Stores numbers in the form
# of its equivalent
strr = str(R)
# Stores overlapping subproblems
dp = [[[-1 for i in range(2)] for i in range(M)]
for i in range(M)]
# Initialize dp[][][]
# memset(dp, -1, sizeof(dp))
# Stores count of numbers
# in the range [0, R]
cntR = cntNum(strr, 0, Y, True, dp)
# Update str
strr = str(L - 1)
# Initialize dp[][][]
# memset(dp, -1, sizeof(dp))
# Stores count of numbers in
# the range [0, L - 1]
cntL = cntNum(strr, 0, Y, True, dp)
return (cntR - cntL)
# Driver Code
if __name__ == '__main__':
L, R, Y = 20, 10000, 14
print(UtilCntNumRange(L, R, Y))
# This code is contributed by mohit kumar 29
C#
// C# program for the above approach
using System;
class GFG{
static readonly int M = 1000;
// Function to find the sum of digits
// of numbers in the range [0, X]
static int cntNum(String X, int i, int sum,
int tight, int [,,]dp)
{
// Check if count of digits in a number
// greater than count of digits in X
if (i >= X.Length || sum < 0)
{
// Check if sum of digits of a
// number is equal to Y
if (sum == 0)
{
return 1;
}
return 0;
}
// Check if current subproblem has
// already been computed
if (dp[sum, i, tight] != -1)
{
return dp[sum, i, tight];
}
// Stores count of numbers whose
// sum of digits is Y
int res = 0;
// Check if the number
// exceeds Y or not
int end = tight != 0 ? X[i] - '0' : 9;
// Iterate over all possible
// values of i-th digits
for(int j = 0; j <= end; j++)
{
// Update res
res += cntNum(X, i + 1, sum - j,
(tight > 0 & (j == end)) ==
true ? 1 : 0, dp);
}
// Return res
return dp[sum][i][tight] = res;
}
// Utility function to count the numbers in
// the range [L, R] whose sum of digits is Y
static int UtilCntNumRange(int L, int R, int Y)
{
// Base Case
if (R == 0 && Y == 0)
{
return 1;
}
// Stores numbers in the form
// of its equivalent String
String str = String.Join("", R);
// Stores overlapping subproblems
int [,,]dp = new int[M, M, 2];
// Initialize [,]dp[]
for(int i = 0; i < M; i++)
{
for(int j = 0; j < M; j++)
{
for(int k = 0; k < 2; k++)
dp[i, j, k] = -1;
}
}
// Stores count of numbers
// in the range [0, R]
int cntR = cntNum(str, 0, Y,
1, dp);
// Update str
str = String.Join("",L - 1);
// Initialize [,]dp[]
for(int i = 0; i < M; i++)
{
for(int j = 0; j < M; j++)
{
for(int k = 0; k < 2; k++)
dp[i, j, k] = -1;
}
}
// Stores count of numbers in
// the range [0, L - 1]
int cntL = cntNum(str, 0, Y,
1, dp);
return (cntR - cntL);
}
// Driver Code
public static void Main(String[] args)
{
int L = 20, R = 10000, Y = 14;
Console.Write(UtilCntNumRange(L, R, Y));
}
}
// This code is contributed by 29AjayKumar
540
时间复杂度: O(Y * log 10 (R)* 10)
辅助空间: O(Y * log 10 (R)