Open In App

Total count of sorted numbers upto N digits in range [L, R] (Magnificent necklace combinatorics problem)

Improve
Improve
Like Article
Like
Save
Share
Report

Given three integers N, L, and R, the task is to print the total count of ways to form a necklace of at most N pearls such that the values of a pearl lie in the range [L, R] and are in ascending order.

Examples:

Input: N = 3, L = 6, R = 9
Output: 34
Explanation:
The necklace can be formed in the following ways:

  1. The necklaces of length one that can be formed are { “6”, “7”, “8”, “9” }.
  2. The necklaces of length two, that can be formed are { “66”, “67”, “68”, “69”, “77”, “78”, “79”, “88”, “89”, “99” }.
  3. The necklaces of length three, that can be formed are { “666”, “667”, “668”, “669”, “677”, “678”, “679”, “688”, “689”, “699”, “777”, “778”, “779”, “788”, “789”, “799”, “888”, “889”, “899”, “999” }.

Thus, in total, the necklace can be formed in (4+10+20 = 34 ) ways.

Input: N = 1, L = 8, R = 9
Output: 2
Explanation:
The necklace can be formed in the following ways: {“8”, “9”}.

Approach: The given problem can be solved based on the following observations: 

  1. The problem can be solved using 2 states dynamic programming with prefix sum.
  2. Suppose Dp(i, j) stores the count of ways to form a necklace of size i with values of pearls in the range [L, j].
  3. Then the transition state at the ith position can be defined as:
    1. For each value j in the range [L, R],
      1. Dp(i, j) = Dp(i – 1, L) + Dp(i – 1, L + 1), …, Dp(i – 1, j – 1)+ Dp(i – 1, j)
  4. The above transition can be optimized by using prefix sum for every i as:
    1. Dp(i, j) = Dp(i, L) + Dp(i, L + 1) +…+ Dp(i, j – 1) + Dp(i, j)
  5. Therefore, now transitions can be defined as:
    1. Dp(i, j) = Dp(i-1, j) + Dp(i, j-1)

Follow the steps below to solve the problem:

  • Initialize a variable, say ans as 0, to store the result.
  • Initialize a 2D array, say Dp[][]  of dimension N * (R – L + 1) as 0 to store all the DP-states.
  • Iterate over the range [0, N – 1] using the variable i, and assign Dp[i][0] = 1.
  • Iterate over the range [1, R – L] using the variable i, and update the Dp[0][i] as Dp[0][i]= Dp[0][i – 1]+1.
  • Assign Dp[0][R – L] to ans.
  • Iterate over the range [1, N – 1] using the variable i, and perform the following operations:
    • Iterate over the range [1, R – L] using the variable j, and update the Dp[i][j] as Dp[i][j] = Dp[i][j – 1] + Dp[i – 1][j].
    • Increment the ans by Dp[i][R – L].
  • Finally, after completing the above steps, print the ans.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to count total number of ways
int Count(int N, int L, int R)
{
    // Stores all DP-states
    vector<vector<int> > dp(N,
                            vector<int>(R - L + 1, 0));
    // Stores the result
    int ans = 0;
 
    // Traverse the range [0, N]
    for (int i = 0; i < N; i++) {
        dp[i][0] = 1;
    }
    // Traverse the range [1, R - L]
    for (int i = 1; i < dp[0].size(); i++) {
 
        // Update dp[i][j]
        dp[0][i] = dp[0][i - 1] + 1;
    }
 
    // Assign dp[0][R-L] to ans
    ans = dp[0][R - L];
 
    // Traverse the range [1, N]
    for (int i = 1; i < N; i++) {
 
        // Traverse the range [1, R - L]
        for (int j = 1; j < dp[0].size(); j++) {
 
            // Update dp[i][j]
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        }
 
        // Increment ans by dp[i-1][j]
        ans += dp[i][R - L];
    }
 
    // Return ans
    return ans;
}
 
// Driver Code
int main()
{
    // Input
    int N = 3;
    int L = 6;
    int R = 9;
 
    // Function call
    cout << Count(N, L, R);
 
    return 0;
}


Java




// Java program for the above approach
import java.util.*;
 
class GFG{
     
// Function to count total number of ways
static int Count(int N, int L, int R)
{
     
    // Stores all DP-states
    int[][] dp = new int[N][R - L + 1];
     
    // Stores the result
    int ans = 0;
 
    // Traverse the range [0, N]
    for(int i = 0; i < N; i++)
    {
        dp[i][0] = 1;
    }
     
    // Traverse the range [1, R - L]
    for(int i = 1; i < dp[0].length; i++)
    {
         
        // Update dp[i][j]
        dp[0][i] = dp[0][i - 1] + 1;
    }
 
    // Assign dp[0][R-L] to ans
    ans = dp[0][R - L];
 
    // Traverse the range [1, N]
    for(int i = 1; i < N; i++)
    {
         
        // Traverse the range [1, R - L]
        for(int j = 1; j < dp[0].length; j++)
        {
             
            // Update dp[i][j]
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        }
 
        // Increment ans by dp[i-1][j]
        ans += dp[i][R - L];
    }
 
    // Return ans
    return ans;
}
 
// Driver Code
public static void main(String args[])
{
     
    // Input
    int N = 3;
    int L = 6;
    int R = 9;
 
    // Function call
    System.out.println(Count(N, L, R));
}
}
 
// This code is contributed by avijitmondal1998


Python3




# Python3 program for the above approach
 
# Function to count total number of ways
def Count(N, L, R):
     
    # Stores all DP-states
    dp = [[0 for i in range(R - L + 1)]
             for i in range(N)]
              
    # Stores the result
    ans = 0
 
    # Traverse the range [0, N]
    for i in range(N):
        dp[i][0] = 1
 
    # Traverse the range [1, R - L]
    for i in range(1, len(dp[0])):
         
        # Update dp[i][j]
        dp[0][i] = dp[0][i - 1] + 1
 
    # Assign dp[0][R-L] to ans
    ans = dp[0][R - L]
 
    # Traverse the range [1, N]
    for i in range(1, N):
         
        # Traverse the range [1, R - L]
        for j in range(1, len(dp[0])):
             
            # Update dp[i][j]
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
 
        # Increment ans by dp[i-1][j]
        ans += dp[i][R - L]
 
    # Return ans
    return ans
 
# Driver Code
if __name__ == '__main__':
     
    # Input
    N = 3
    L = 6
    R = 9
 
    # Function call
    print(Count(N, L, R))
     
# This code is contributed by mohit kumar 29


C#




// C# program for the above approach
using System;
 
class GFG{
 
// Function to count total number of ways
static int Count(int N, int L, int R)
{
     
    // Stores all DP-states
    int[,] dp = new int[N, R - L + 1];
 
    // Stores the result
    int ans = 0;
 
    // Traverse the range [0, N]
    for(int i = 0; i < N; i++)
    {
        dp[i, 0] = 1;
    }
 
    // Traverse the range [1, R - L]
    for(int i = 1; i < dp.GetLength(1); i++)
    {
         
        // Update dp[i][j]
        dp[0, i] = dp[0, i - 1] + 1;
    }
 
    // Assign dp[0][R-L] to ans
    ans = dp[0, R - L];
 
    // Traverse the range [1, N]
    for(int i = 1; i < N; i++)
    {
         
        // Traverse the range [1, R - L]
        for(int j = 1; j < dp.GetLength(1); j++)
        {
             
            // Update dp[i][j]
            dp[i, j] = dp[i - 1, j] + dp[i, j - 1];
        }
 
        // Increment ans by dp[i-1][j]
        ans += dp[i, R - L];
    }
 
    // Return ans
    return ans;
}
 
// Driver Code
public static void Main()
{
     
    // Input
    int N = 3;
    int L = 6;
    int R = 9;
 
    // Function call
    Console.Write(Count(N, L, R));
}
}
 
// This code is contributed by ukasp


Javascript




<script>
// Javascript program for the above approach
 
// Function to count total number of ways
function Count(N, L, R) {
    // Stores all DP-states
    let dp = new Array(N).fill(0).map(() => new Array(R - L + 1).fill(0));
 
    // Stores the result
    let ans = 0;
 
    // Traverse the range [0, N]
    for (let i = 0; i < N; i++) {
        dp[i][0] = 1;
    }
    // Traverse the range [1, R - L]
    for (let i = 1; i < dp[0].length; i++) {
 
        // Update dp[i][j]
        dp[0][i] = dp[0][i - 1] + 1;
    }
 
    // Assign dp[0][R-L] to ans
    ans = dp[0][R - L];
 
    // Traverse the range [1, N]
    for (let i = 1; i < N; i++) {
 
        // Traverse the range [1, R - L]
        for (let j = 1; j < dp[0].length; j++) {
 
            // Update dp[i][j]
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        }
 
        // Increment ans by dp[i-1][j]
        ans += dp[i][R - L];
    }
 
    // Return ans
    return ans;
}
 
// Driver Code
 
// Input
let N = 3;
let L = 6;
let R = 9;
 
// Function call
document.write(Count(N, L, R));
 
// This code is contributed by _saurabh_jaiswal.
</script>


Output

34

Time Complexity: O(N * (R – L))
Auxiliary Space: O(N * (R – L))



Last Updated : 28 Jul, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads