A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://www.geeksforgeeks.org/competitive-programming/cses-solutions-counting-numbers/ below:

CSES Solutions - Counting Numbers

CSES Solutions - Counting Numbers

Last Updated : 08 Apr, 2024

Given two integers a and b. Your task is to count the number of integers between a and b where no two adjacent digits are the same.

Examples:

Input: a=11, b=13
Output: 2
Explanation: The two numbers are 12 and 13.

Input: a=123, b=321
Output: 171

Approach:

The idea is to use digit DP to solve this problem. The dp array dp[n][prev_digit][leading_zero][tight] represents count of valid numbers(whose adjacent digits are not same) formed by the n digits.

The parameters can be described as following:

During the transition, the code iterates through possible digits for the current position, checking their validity by ensuring they differ from the previous digit and, if applicable, allowing consecutive leading zeroes. The state is then updated by recursively calling the mem function for the next position, adjusting flags like leading_zero and tight accordingly. The count of valid numbers is accumulated by considering different digit choices, and memoization is applied to optimize repetitive calculations.

The final answer will be the difference between count of valid numbers from [0,b] and [0,a-1].

Follow the steps to solve the problem:

Below is the implementation of above approach:

C++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

// dp array to memoize results of subproblems
ll dp[20][10][2][2];

// Function to calculate the count of valid numbers using Digit DP
ll mem(string s, ll curr, ll prev_digit, ll leading_zero, ll tight)
{
    // Base case: entire number processed
    if (curr == 0)
    {
        return 1;
    }

    // Check if result for the current state is already computed
    if (dp[curr][prev_digit][leading_zero][tight] != -1)
        return dp[curr][prev_digit][leading_zero][tight];

    // Determine the limit for the current position based on tightness
    ll limit;
    if (tight == 0)
    {
        limit = 9;
    }
    else
    {
        ll sz = s.size();
        limit = s[sz - curr] - 48;
    }

    ll countNumbers = 0;

    // Iterate through possible digits for the current position
    for (ll curr_digit = 0; curr_digit <= limit; curr_digit++)
    {
        // Check validity based on constraints
        if (leading_zero == 0 && (curr_digit == prev_digit))
        {
            continue;
        }

        // Update state parameters based on the current digit
        ll new_leading_zero = (leading_zero == 1 && curr_digit == 0) ? 1 : 0;
        ll new_tight = (curr_digit == limit && tight == 1) ? 1 : 0;

        // Recursively call the mem function for the next position
        countNumbers += mem(s, curr - 1, curr_digit, new_leading_zero, new_tight);
    }

    // Update the memoization table with the count of valid numbers for the current state
    dp[curr][prev_digit][leading_zero][tight] = countNumbers;
  
    return dp[curr][prev_digit][leading_zero][tight];
}

// Driver Code
int main()
{
    ll a=123, b=321;
    
    ll count1 = 0;
    // Initialize dp table with -1
    memset(dp, -1, sizeof(dp));

    // Calculate count of valid numbers from [0, a-1]
    string str1 = to_string(a - 1);
    if (a != 0)
        count1 = mem(str1, str1.size(), -1, 1, 1);

    // Calculate count of valid numbers from [0, b]
    memset(dp, -1, sizeof(dp));
    string str2 = to_string(b);
    ll count2 = mem(str2, str2.size(), -1, 1, 1);

    // Output the difference between count of valid numbers from [0, b] and [0, a-1]
    cout << count2 - count1;
}
Java
import java.util.Arrays;

public class Main {
    // dp array to memoize results of subproblems
    static long[][][][] dp = new long[20][10][2][2];

    // Function to calculate the count of valid numbers using Digit DP
    static long mem(String s, int curr, int prev_digit, int leading_zero, int tight) {
        // Base case: entire number processed
        if (curr == 0) {
            return 1;
        }

        // Check if result for the current state is already computed
        if (dp[curr][prev_digit][leading_zero][tight] != -1)
            return dp[curr][prev_digit][leading_zero][tight];

        // Determine the limit for the current position based on tightness
      int limit;
        if (tight == 0) {
            limit = 9;
        } else {
            int sz = s.length();
            limit = s.charAt(sz - curr) - '0';
        }

        long countNumbers = 0;

        // Iterate through possible digits for the current position
        for (int curr_digit = 0; curr_digit <= limit; curr_digit++) {
            // Check validity based on constraints
            if (leading_zero == 0 && (curr_digit == prev_digit)) {
                continue;
            }

            // Update state parameters based on the current digit
            int new_leading_zero = (leading_zero == 1 && curr_digit == 0) ? 1 : 0;
            int new_tight = (curr_digit == limit && tight == 1) ? 1 : 0;

            // Recursively call the mem function for the next position
            countNumbers += mem(s, curr - 1, curr_digit, new_leading_zero, new_tight);
        }

        // Update the memoization table with the count of valid numbers for the current state
        dp[curr][prev_digit][leading_zero][tight] = countNumbers;

        return dp[curr][prev_digit][leading_zero][tight];
    }

    public static void main(String[] args) {
        long a = 123, b = 321;

        long count1 = 0;
        // Initialize dp table with -1
        for (long[][][] arr3D : dp) {
            for (long[][] arr2D : arr3D) {
                for (long[] arr1D : arr2D) {
                    Arrays.fill(arr1D, -1);
                }
            }
        }

        // Calculate count of valid numbers from [0, a-1]
        String str1 = Long.toString(a - 1);
        if (a != 0)
            count1 = mem(str1, str1.length(), 0, 1, 1);

        // Calculate count of valid numbers from [0, b]
        for (long[][][] arr3D : dp) {
            for (long[][] arr2D : arr3D) {
                for (long[] arr1D : arr2D) {
                    Arrays.fill(arr1D, -1);
                }
            }
        }
        String str2 = Long.toString(b);
        long count2 = mem(str2, str2.length(), 0, 1, 1);

        // Output the difference between count of valid numbers from [0, b] and [0, a-1]
        System.out.println(count2 - count1);
    }
}
Python3
def mem(s, curr, prev_digit, leading_zero, tight):
    # Base case: if current position is 0, return 1
    if curr == 0:
        return 1

    # Check if result for the current state is already computed
    if dp[curr][prev_digit][leading_zero][tight] != -1:
        return dp[curr][prev_digit][leading_zero][tight]

    # Determine the limit for the current position based on tightness
    limit = 9 if tight == 0 else int(s[len(s) - curr])

    count_numbers = 0

    # Iterate through possible digits for the current position
    for curr_digit in range(limit + 1):
        # Check validity based on constraints
        if leading_zero == 0 and curr_digit == prev_digit:
            continue

        # Update state parameters based on the current digit
        new_leading_zero = 1 if leading_zero == 1 and curr_digit == 0 else 0
        new_tight = 1 if curr_digit == limit and tight == 1 else 0

        # Recursively call the mem function for the next position
        count_numbers += mem(s, curr - 1, curr_digit, new_leading_zero, new_tight)

    # Update the memoization table with the count of valid numbers 
    # for the current state
    dp[curr][prev_digit][leading_zero][tight] = count_numbers

    return count_numbers

# Define input values
a, b = 123, 321
count1 = 0

# Initialize dp table with -1
dp = [[[[ -1 for _ in range(2)] for _ in range(2)] for _ in range(10)] for _ in range(20)]

# Calculate count of valid numbers from [0, a-1]
str1 = str(a - 1)
if a != 0:
    count1 = mem(str1, len(str1), -1, 1, 1)

# Reset dp table with -1
dp = [[[[ -1 for _ in range(2)] for _ in range(2)] for _ in range(10)] for _ in range(20)]

# Calculate count of valid numbers from [0, b]
str2 = str(b)
count2 = mem(str2, len(str2), -1, 1, 1)

# Output the difference between count of valid numbers from [0, b] and [0, a-1]
print(count2 - count1)
JavaScript
function GFG(s, curr, prev_digit, leading_zero, tight) {
    // Base case: entire number processed
    if (curr === 0) {
        return 1;
    }
    // Determine the limit for current position based on tightness
    let limit = (tight === 0) ? 9 : parseInt(s[s.length - curr]);
    let countNumbers = 0;
    // Iterate through possible digits for current position
    for (let curr_digit = 0; curr_digit <= limit; curr_digit++) {
        if (leading_zero === 0 && (curr_digit === prev_digit)) {
            continue;
        }
        let new_leading_zero = (leading_zero === 1 && curr_digit === 0) ? 1 : 0;
        let new_tight = (curr_digit === limit && tight === 1) ? 1 : 0;
        // Recursively call the mem function for the next position
        countNumbers += GFG(s, curr - 1, curr_digit, new_leading_zero, new_tight);
    }
    return countNumbers;
}
// Driver Code
function main() {
    let a = 123, b = 321;
    let count1 = 0;
    let str1 = (a - 1).toString();
    if (a !== 0) {
        count1 = GFG(str1, str1.length, -1, 1, 1);
    }
    // Calculate count of valid numbers from [0, b]
    let str2 = b.toString();
    let count2 = GFG(str2, str2.length, -1, 1, 1);
    // Output the difference between count of the valid numbers from [0, b] and [0, a-1]
    console.log(count2 - count1);
}
main();

Time Complexity: O(n*100), where n is number of digits of number n.
Auxilary Space: O(n*100)



RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4