Given three positive integers N, X, and Y, the task is to count N-digit numbers containing of X or Y only as digits and the sum of digits also contains X or Y. Since the count can be very large, print the count modulo 109 + 7.
Examples:
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.
Naive Approach: The simplest approach to solve this problem by using recursion. At each step, there are 2 choices, to place digit X or Y at the current position and calculate the sum of digits when the length of the formed number becomes equal to N. If the sum is also formed of only X or Y the count this number. After checking all the numbers print the count modulo 109 + 7.Â
Time Complexity: O(2N)
Auxiliary Space: O(1)
Efficient Approach: The above approach can be optimized by using Dynamic Programming since this problem has both properties of Optimal Substructure and Overlapping Subproblems. The computations of the same subproblems can be avoided by using an auxiliary array dp[N][sum] to store the value when the number of digits left is N and the sum of filled digits is the sum. Below are the steps:
- Initialize an auxiliary array dp[][] to store intermediate computations.
- At each step, there are 2 choices to place digit X or Y at the current position.
- When the number of digits left is 0, check if the sum of digits can be made using X or Y. If yes then increment the current state value by 1.
- Else Update the current state as 0.
- If the same subproblem is encountered, return the already computed value modulo 109 + 7.
- Place digit X and digit Y at the current position and recur for the remaining positions, and pass the sum of digits at each step.
- For each recursive call for value x and y, update the current state as the sum of values returned by these states.
- After the above steps, print the value of dp[N][0] as the resultant count.
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> 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
<script> Â
// JavaScript program for the above approach Â
// Stores the value of overlapping // states let dp = []; for (let i = 0;i<1005;i++){ Â Â Â dp[i] = []; Â Â Â for (let j = 0;j<9005;j++){ Â Â Â Â Â Â Â Â dp[i][j] = 0; Â Â Â } } let mod = 1000000007; Â
// Function to check whether a number // have only digits X or Y or not function check( sum, x, y) {     // Until sum is positive     while (sum > 0) { Â
        let ln = sum % 10; Â
        // If any digit is not         // X or Y then return 0         if (ln != x && ln != y) {             return 0;         }         sum = Math.floor(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 function countNumbers(n, x, y, sum) {     // Initialize dp array     for (let i = 0;i<1005;i++){    for (let j = 0;j<9005;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     let option1 = countNumbers(n - 1, x,                                y, sum + x) % mod; Â
    // Place the digit Y at the     // current position     let option2 = countNumbers(n - 1, x,                                y, sum + y) % mod; Â
    // Update current state result     return dp[n][sum] = (option1 + option2) % mod; } Â
// Driver Code let N = 3, X = 1, Y = 5; Â
    // Function Call     document.write(countNumbers(N, X, Y, 0) % mod); Â
</script> |
4
Time Complexity:(N*sum)
Auxiliary Space: O(N*sum)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memorization(top-down) because memorization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a vector to store the solution of the subproblems.
- Initialize the table with base cases
- Fill up the table iteratively
- Return the final solution
Implementation :
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; Â
const int N = 1000 + 5, M = 9000 + 5, MOD = 1000000007; Â
int dp[N][M]; Â
// Function to check whether a number // have only digits X or Y or not int check( int sum, int x, int y) { Â Â Â Â while (sum > 0) { Â Â Â Â Â Â Â Â int ln = sum % 10; Â Â Â Â Â Â Â Â if (ln != x && ln != y) { Â Â Â Â Â Â Â Â Â Â Â Â return 0; Â Â Â Â Â Â Â Â } Â Â Â Â Â Â Â Â sum /= 10; Â Â Â Â } Â Â Â Â 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, 0, sizeof (dp));          // base case     dp[0][0] = 1; Â
    for ( int i = 1; i <= n; i++) {         for ( int j = 0; j <= sum; j++) {                          // Place the digit X at the             // current position             int option1 = (j >= x ? dp[i-1][j-x] : 0);             // Place the digit Y at the             // current position             int option2 = (j >= y ? dp[i-1][j-y] : 0);             // Update current state result             dp[i][j] = (option1 + option2) % MOD;         }     }          // get answer     int ans = 0;     for ( int i = 0; i <= sum; i++) {         // update answer         ans = (ans + check(i, x, y) * dp[n][i]) % MOD;     } Â
    return ans; } Â
// Driver code int main() { Â Â Â Â int n = 3, x = 1, y = 5; Â Â Â Â cout << countNumbers(n, x, y, 9000) << endl; Â Â Â Â return 0; } Â
// This code is contributed by bhardwajji |
Java
import java.io.*; import java.util.Arrays; Â
class GFG{ Â Â static final int N = 1000 + 5 , M = 9000 + 5 , MOD = 1000000007 ; Â
  static int [][] dp = new int [N][M]; Â
  // Function to check whether a number   // have only digits X or Y or not   static int check( int sum, int x, int y) {     while (sum > 0 ) {       int ln = sum % 10 ;       if (ln != x && ln != y) {         return 0 ;       }       sum /= 10 ;     }     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   static int countNumbers( int n, int x, int y, int sum)   {          // Initialize dp array     for ( int [] row : dp)       Arrays.fill(row, 0 ); Â
    // base case     dp[ 0 ][ 0 ] = 1 ; Â
    for ( int i = 1 ; i <= n; i++) {       for ( int j = 0 ; j <= sum; j++) { Â
        // Place the digit X at the         // current position         int option1 = (j >= x ? dp[i - 1 ][j - x] : 0 );                  // Place the digit Y at the         // current position         int option2 = (j >= y ? dp[i - 1 ][j - y] : 0 );                  // Update current state result         dp[i][j] = (option1 + option2) % MOD;       }     } Â
    // get answer     int ans = 0 ;     for ( int i = 0 ; i <= sum; i++)     {              // update answer       ans = (ans + check(i, x, y) * dp[n][i]) % MOD;     } Â
    return ans;   } Â
  public static void main(String[] args) {     int n = 3 , x = 1 , y = 5 ;     System.out.println(countNumbers(n, x, y, 9000 ));   } } |
Python
MOD = 1000000007 N = 1000 + 5 M = 9000 + 5 Â
dp = [[ 0 for j in range (M)] for i in range (N)] Â
# Function to check whether a number # have only digits X or Y or not def check( sum , x, y): Â Â Â Â while sum > 0 : Â Â Â Â Â Â Â Â ln = sum % 10 Â Â Â Â Â Â Â Â if ln ! = x and ln ! = y: Â Â Â Â Â Â Â Â Â Â Â Â return 0 Â Â Â Â Â Â Â Â sum / / = 10 Â Â Â Â 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     for i in range (N):         for j in range (M):             dp[i][j] = 0          # base case     dp[ 0 ][ 0 ] = 1 Â
    for i in range ( 1 , n + 1 ):         for j in range ( sum + 1 ):                          # Place the digit X at the             # current position             option1 = dp[i - 1 ][j - x] if j > = x else 0             # Place the digit Y at the             # current position             option2 = dp[i - 1 ][j - y] if j > = y else 0             # Update current state result             dp[i][j] = (option1 + option2) % MOD          # get answer     ans = 0     for i in range ( sum + 1 ):         # update answer         ans = (ans + check(i, x, y) * dp[n][i]) % MOD Â
    return ans Â
# Driver code if __name__ = = "__main__" : Â Â Â Â n = 3 Â Â Â Â x = 1 Â Â Â Â y = 5 Â Â Â Â print (countNumbers(n, x, y, 9000 )) |
C#
using System; Â
class GFG { Â Â Â Â const int N = 1000 + 5; Â Â Â Â const int M = 9000 + 5; Â Â Â Â const int MOD = 1000000007; Â
    static int [,] dp = new int [N, M]; Â
    // Function to check whether a number     // has only digits X or Y or not     static int Check( int sum, int x, int y)     {         while (sum > 0)         {             int ln = sum % 10;             if (ln != x && ln != y)             {                 return 0;             }             sum /= 10;         }         return 1;     } Â
    // Function to find the count of     // numbers that are formed by digits     // X and Y and whose sum of digits     // also has digit X or Y     static int CountNumbers( int n, int x, int y, int sum)     {         // Initialize dp array         for ( int i = 0; i < N; i++)         {             for ( int j = 0; j < M; j++)             {                 dp[i, j] = 0;             }         } Â
        // Base case         dp[0, 0] = 1; Â
        for ( int i = 1; i <= n; i++)         {             for ( int j = 0; j <= sum; j++)             {                 // Place the digit X at the                 // current position                 int option1 = (j >= x) ? dp[i - 1, j - x] : 0;                 // Place the digit Y at the                 // current position                 int option2 = (j >= y) ? dp[i - 1, j - y] : 0;                 // Update the current state result                 dp[i, j] = (option1 + option2) % MOD;             }         } Â
        // Get the answer         int ans = 0;         for ( int i = 0; i <= sum; i++)         {             // Update the answer             ans = (ans + Check(i, x, y) * dp[n, i]) % MOD;         } Â
        return ans;     } Â
    // Driver code     static void Main()     {         int n = 3, x = 1, y = 5;         Console.WriteLine(CountNumbers(n, x, y, 9000));     } } |
Javascript
// Nikunj Sonigara Â
// JavaScript program for the above approach Â
const N = 1000 + 5; const M = 9000 + 5; const MOD = 1000000007; Â
let dp = new Array(N); for (let i = 0; i < N; i++) { Â Â Â Â dp[i] = new Array(M).fill(0); } Â
// Function to check whether a number // have only digits X or Y or not function check(sum, x, y) { Â Â Â Â while (sum > 0) { Â Â Â Â Â Â Â Â let ln = sum % 10; Â Â Â Â Â Â Â Â if (ln !== x && ln !== y) { Â Â Â Â Â Â Â Â Â Â Â Â return 0; Â Â Â Â Â Â Â Â } Â Â Â Â Â Â Â Â sum = Math.floor(sum / 10); Â Â Â Â } Â Â Â Â 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 function countNumbers(n, x, y, sum) {     // Initialize dp array     for (let i = 0; i <= n; i++) {         for (let j = 0; j <= sum; j++) {             dp[i][j] = 0;         }     } Â
    // base case     dp[0][0] = 1; Â
    for (let i = 1; i <= n; i++) {         for (let j = 0; j <= sum; j++) {             // Place the digit X at the             // current position             let option1 = (j >= x ? dp[i - 1][j - x] : 0);             // Place the digit Y at the             // current position             let option2 = (j >= y ? dp[i - 1][j - y] : 0);             // Update current state result             dp[i][j] = (option1 + option2) % MOD;         }     } Â
    // get answer     let ans = 0;     for (let i = 0; i <= sum; i++) {         // update answer         ans = (ans + check(i, x, y) * dp[n][i]) % MOD;     } Â
    return ans; } Â
// Driver code const n = 3; const x = 1; const y = 5; console.log(countNumbers(n, x, y, 9000)); |
Output
4
Time Complexity: (N*sum)
Auxiliary Space: O(N*sum)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!