Open In App

Count numbers from given range having odd digits at odd places and even digits at even places

Improve
Improve
Like Article
Like
Save
Share
Report

Given two integers L and R, the task is to count numbers from the range [L, R] having odd digits at odd positions and even digits at even positions respectively.

Examples:

Input: L = 3, R = 25
Output: 9
Explanation: The numbers satisfying the conditions are 3, 5, 7, 9, 10, 12, 14, 16 and 18.

Input: L = 128, R = 162
Output: 7
Explanation: The numbers satisfying the conditions are 129, 141, 143, 145, 147, 149 and 161.

 

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

It can be observed that every even position has 5 choices {0, 2, 4, 6, 8} and every odd position also has 5 choices {1, 3, 5, 7, 9}. Therefore, there are 5 possibilities for every position. Considering d to be the number of digits in any number satisfying the condition and D to be the number of digits in N, following observations can be made:

  • Case 1: If d < D, then the count of total numbers consisting of d digits satisfying the condition is 5d as every number has 5 choices and numbers made will all be less than N.
  • Case 2: If D = d, then the count of total numbers satisfying the condition of length d is 5d . But the numbers exceeding N needs to be discarded, which is determined by the following: 
    • For even places, if the digit in pth place is x, then (5 — (x / 2 + 1)) * 5(D — p) numbers are greater than N.
    • For odd places, if the digit in pth place is x, then (5 — (x + 1) / 2) * 5(D — p) numbers will be greater than N.

Follow the steps below to solve the problem:

  • Define a function countNumberUtill() for count the numbers from the range [1, N], satisfying the condition, where N is a natural number.
  • Initialize an integer variable, count and vector digits to store the digits of the integer N.
  • Traverse over all the digits of given number, i.e. from 1 to D, and perform the following: 
    • Store the 5i in variable, say res.
    • Traverse from p = 1 to p = D and perform the following: 
      • Initialize a variable x and store x = digits[p] in it.
      • If p is even, then subtract (5 — (x / 2 + 1)) * 5(D— p) from res.
      • Otherwise, subtract (5 — (x + 1) / 2) * 5(D — p) from res.
  • Add res to the count.
  • Return the count.
  • Print countNumberUtill(R) — countNumberUtill(L – 1) as the required answer.

Below is the implementation of the above approach:

C++




// C++ program to implement
// the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
#define ll long long
 
// Function to calculate 5^p
ll getPower(int p)
{
    // Stores the result
    ll res = 1;
 
    // Multiply 5 p times
    while (p--) {
        res *= 5;
    }
 
    // Return the result
    return res;
}
 
// Function to count all numbers upto N
// having odd digits at odd places and
// even digits at even places
ll countNumbersUtil(ll N)
{
    // Stores the count
    ll count = 0;
 
    // Stores the digits of N
    vector<int> digits;
 
    // Insert the digits of N
    while (N) {
        digits.push_back(N % 10);
        N /= 10;
    }
 
    // Reverse the vector to arrange
    // the digits from first to last
    reverse(digits.begin(), digits.end());
 
    // Stores count of digits of n
    int D = digits.size();
 
    for (int i = 1; i <= D; i++) {
 
        // Stores the count of numbers
        // with i digits
        ll res = getPower(i);
 
        // If the last digit is reached,
        // subtract numbers eceeding range
        if (i == D) {
 
            // Iterate over all the places
            for (int p = 1; p <= D; p++) {
 
                // Stores the digit in the pth place
                int x = digits[p - 1];
 
                // Stores the count of numbers
                // having a digit greater than x
                // in the p-th position
                ll tmp = 0;
 
                // Calculate the count of numbers
                // exceeding the range if p is even
                if (p % 2 == 0) {
                    tmp = (5 - (x / 2 + 1))
                          * getPower(D - p);
                }
 
                // Calculate the count of numbers
                // exceeding the range if p is odd
                else {
                    tmp = (5 - (x + 1) / 2)
                          * getPower(D - p);
                }
 
                // Subtract the count of numbers
                // exceeding the range from total count
                res -= tmp;
 
                // If the parity of p and the
                // parity of x are not same
                if (p % 2 != x % 2) {
                    break;
                }
            }
        }
 
        // Add count of numbers having i digits
        // and satisfies the given conditions
        count += res;
    }
 
    // Return the total count of numbers till n
    return count;
}
 
// Function to calculate the count of numbers
// from given range having odd digits places
// and even digits at even places
void countNumbers(ll L, ll R)
{
    // Count of numbers in range [L, R] =
    // Count of numbers till R -
    cout << (countNumbersUtil(R)
 
             // Count of numbers till (L-1)
             - countNumbersUtil(L - 1))
         << endl;
}
 
// Driver Code
int main()
{
    ll L = 128, R = 162;
    countNumbers(L, R);
 
    return 0;
}


Java




// Java program to implement
// the above approach
import java.util.*;
import java.util.Vector;
import java.util.Collections;
 
class GFG{
     
// Function to calculate 5^p
static int getPower(int p)
{
     
    // Stores the result
    int res = 1;
     
    // Multiply 5 p times
    while (p > 0)
    {
        res *= 5;
        p--;
    }
     
    // Return the result
    return res;
}
 
// Function to count all numbers upto N
// having odd digits at odd places and
// even digits at even places
static int countNumbersUtil(int N)
{
     
    // Stores the count
    int count = 0;
     
    // Stores the digits of N
    Vector<Integer> digits = new Vector<Integer>();
     
    // Insert the digits of N
    while (N > 0)
    {
        digits.add(N % 10);
        N /= 10;
    }
 
    // Reverse the vector to arrange
    // the digits from first to last
    Collections.reverse(digits);
 
    // Stores count of digits of n
    int D = digits.size();
 
    for(int i = 1; i <= D; i++)
    {
         
        // Stores the count of numbers
        // with i digits
        int res = getPower(i);
 
        // If the last digit is reached,
        // subtract numbers eceeding range
        if (i == D)
        {
             
            // Iterate over all the places
            for(int p = 1; p <= D; p++)
            {
                 
                // Stores the digit in the pth place
                int x = digits.get(p - 1);
                 
                // Stores the count of numbers
                // having a digit greater than x
                // in the p-th position
                int tmp = 0;
                 
                // Calculate the count of numbers
                // exceeding the range if p is even
                if (p % 2 == 0)
                {
                    tmp = (5 - (x / 2 + 1)) *
                           getPower(D - p);
                }
 
                // Calculate the count of numbers
                // exceeding the range if p is odd
                else
                {
                    tmp = (5 - (x + 1) / 2) *
                       getPower(D - p);
                }
 
                // Subtract the count of numbers
                // exceeding the range from total count
                res -= tmp;
 
                // If the parity of p and the
                // parity of x are not same
                if (p % 2 != x % 2)
                {
                    break;
                }
            }
        }
 
        // Add count of numbers having i digits
        // and satisfies the given conditions
        count += res;
    }
 
    // Return the total count of numbers till n
    return count;
}
 
// Function to calculate the count of numbers
// from given range having odd digits places
// and even digits at even places
static void countNumbers(int L, int R)
{
     
    // Count of numbers in range [L, R] =
    // Count of numbers till R -
    System.out.println(countNumbersUtil(R) -
     
                       // Count of numbers till (L-1)
                       countNumbersUtil(L - 1));
}
 
// Driver Code
public static void main(String args[])
{
    int L = 128, R = 162;
     
    countNumbers(L, R);
}
}
 
// This code is contributed by ipg2016107


Python3




# Python3 program to implement
# the above approach
 
# Function to calculate 5^p
def getPower(p) :
     
    # Stores the result
    res = 1
  
    # Multiply 5 p times
    while (p) :
        res *= 5
        p -= 1
      
    # Return the result
    return res
 
# Function to count anumbers upto N
# having odd digits at odd places and
# even digits at even places
def countNumbersUtil(N) :
     
    # Stores the count
    count = 0
  
    # Stores the digits of N
    digits = []
  
    # Insert the digits of N
    while (N) :
        digits.append(N % 10)
        N //= 10
      
    # Reverse the vector to arrange
    # the digits from first to last
    digits.reverse() 
  
    # Stores count of digits of n
    D = len(digits)
  
    for i in range(1, D + 1, 1) :
  
        # Stores the count of numbers
        # with i digits
        res = getPower(i)
  
        # If the last digit is reached,
        # subtract numbers eceeding range
        if (i == D) :
  
            # Iterate over all the places
            for p in range(1, D + 1, 1) :
  
                # Stores the digit in the pth place
                x = digits[p - 1]
  
                # Stores the count of numbers
                # having a digit greater than x
                # in the p-th position
                tmp = 0
  
                # Calculate the count of numbers
                # exceeding the range if p is even
                if (p % 2 == 0) :
                    tmp = ((5 - (x // 2 + 1))
                            * getPower(D - p))
                 
                # Calculate the count of numbers
                # exceeding the range if p is odd
                else :
                    tmp = ((5 - (x + 1) // 2)
                            * getPower(D - p))
                 
                # Subtract the count of numbers
                # exceeding the range from total count
                res -= tmp
  
                # If the parity of p and the
                # parity of x are not same
                if (p % 2 != x % 2) :
                    break
                 
        # Add count of numbers having i digits
        # and satisfies the given conditions
        count += res
     
    # Return the total count of numbers tin
    return count
 
# Function to calculate the count of numbers
# from given range having odd digits places
# and even digits at even places
def countNumbers(L, R) :
     
    # Count of numbers in range [L, R] =
    # Count of numbers tiR -
    print(countNumbersUtil(R)
     
             # Count of numbers ti(L-1)
            - countNumbersUtil(L - 1))
 
# Driver Code
 
L = 128
R = 162
   
countNumbers(L, R) 
 
# This code is contributed by code_hunt


C#




// C# program for
// the above approach
using System;
using System.Collections.Generic;
 
class GFG{
     
// Function to calculate 5^p
static int getPower(int p)
{
     
    // Stores the result
    int res = 1;
     
    // Multiply 5 p times
    while (p > 0)
    {
        res *= 5;
        p--;
    }
     
    // Return the result
    return res;
}
 
// Function to count all numbers upto N
// having odd digits at odd places and
// even digits at even places
static int countNumbersUtil(int N)
{
     
    // Stores the count
    int count = 0;
     
    // Stores the digits of N
    List<int> digits = new List<int>();
     
    // Insert the digits of N
    while (N > 0)
    {
        digits.Add(N % 10);
        N /= 10;
    }
 
    // Reverse the vector to arrange
    // the digits from first to last
    digits.Reverse();
 
    // Stores count of digits of n
    int D = digits.Count;
 
    for(int i = 1; i <= D; i++)
    {
         
        // Stores the count of numbers
        // with i digits
        int res = getPower(i);
 
        // If the last digit is reached,
        // subtract numbers eceeding range
        if (i == D)
        {
             
            // Iterate over all the places
            for(int p = 1; p <= D; p++)
            {
                 
                // Stores the digit in the pth place
                int x = digits[p - 1];
                 
                // Stores the count of numbers
                // having a digit greater than x
                // in the p-th position
                int tmp = 0;
                 
                // Calculate the count of numbers
                // exceeding the range if p is even
                if (p % 2 == 0)
                {
                    tmp = (5 - (x / 2 + 1)) *
                           getPower(D - p);
                }
 
                // Calculate the count of numbers
                // exceeding the range if p is odd
                else
                {
                    tmp = (5 - (x + 1) / 2) *
                       getPower(D - p);
                }
 
                // Subtract the count of numbers
                // exceeding the range from total count
                res -= tmp;
 
                // If the parity of p and the
                // parity of x are not same
                if (p % 2 != x % 2)
                {
                    break;
                }
            }
        }
 
        // Add count of numbers having i digits
        // and satisfies the given conditions
        count += res;
    }
 
    // Return the total count of numbers till n
    return count;
}
 
// Function to calculate the count of numbers
// from given range having odd digits places
// and even digits at even places
static void countNumbers(int L, int R)
{
     
    // Count of numbers in range [L, R] =
    // Count of numbers till R -
    Console.WriteLine(countNumbersUtil(R) -
     
                       // Count of numbers till (L-1)
                       countNumbersUtil(L - 1));
}
 
 
// Driver Code
public static void Main(String[] args)
{
    int L = 128, R = 162;
     
    countNumbers(L, R);
}
}
 
// This code is contributed by jana_sayantan


Javascript




<script>
 
// JavaScript  Program for the above approach
 
// Function to calculate 5^p
function getPower(p)
{
    // Stores the result
    var res = 1;
 
    // Multiply 5 p times
    while (p--) {
        res *= 5;
    }
 
    // Return the result
    return res;
}
 
// Function to count all numbers upto N
// having odd digits at odd places and
// even digits at even places
function countNumbersUtil( N)
{
    // Stores the count
    var count = 0;
 
    // Stores the digits of N
    var digits= [];
 
    // Insert the digits of N
    while (N) {
        digits.push(N % 10);
        N = parseInt(N / 10);
    }
 
    // Reverse the vector to arrange
    // the digits from first to last
    digits.reverse();
 
    // Stores count of digits of n
    var D = digits.length;
 
    for (var i = 1; i <= D; i++) {
 
        // Stores the count of numbers
        // with i digits
        var res = getPower(i);
 
        // If the last digit is reached,
        // subtract numbers eceeding range
        if (i == D) {
 
            // Iterate over all the places
            for (var p = 1; p <= D; p++) {
 
                // Stores the digit in the pth place
                var x = digits[p - 1];
 
                // Stores the count of numbers
                // having a digit greater than x
                // in the p-th position
                var tmp = 0;
 
                // Calculate the count of numbers
                // exceeding the range if p is even
                if (p % 2 == 0) {
                    tmp = (5 - parseInt(x / (2 + 1)))
                          * getPower(D - p);
                }
 
                // Calculate the count of numbers
                // exceeding the range if p is odd
                else {
                    tmp = (5 - parseInt( (x + 1) / 2))
                          * getPower(D - p);
                }
 
                // Subtract the count of numbers
                // exceeding the range from total count
                res -= tmp;
 
                // If the parity of p and the
                // parity of x are not same
                if (p % 2 != x % 2) {
                    break;
                }
            }
        }
 
        // Add count of numbers having i digits
        // and satisfies the given conditions
        count += res;
    }
 
    // Return the total count of numbers till n
    return count;
}
 
// Function to calculate the count of numbers
// from given range having odd digits places
// and even digits at even places
function countNumbers(L, R)
{
    // Count of numbers in range [L, R] =
    // Count of numbers till R -
    document.write( (countNumbersUtil(R)
 
             // Count of numbers till (L-1)
             - countNumbersUtil(L - 1)) + "<br>");
}
 
var L = 128, R = 162;
countNumbers(L, R);
 
// This code is contributed by SoumikMondal
 
</script>


Output

7

Time Complexity: O(N2), where N is the number of digits in R
Auxiliary Space: O(1)

Efficient Digit DP Approach:

The main idea of the code is to use a recursive function f to count the valid numbers based on the given conditions. The function takes several parameters: nums (the string representation of the current number), idx (the current index being considered), even (a flag indicating whether the current position is even or odd), leadingZero (a flag indicating whether the number has leading zeros), and tight (a flag indicating whether the current digit is at its tightest limit based on the range).

  • The function f uses memoization to store the results of subproblems in the 4-dimensional DP array dp. The dimensions of dp represent: the number of digits, the even/odd flag, the leading zero flag, and the tight flag.
  • The base case is when idx reaches 0, which means all the digits have been considered. In this case, the function returns 1, indicating that a valid number has been found.
  • The function f then proceeds to calculate the count by considering two cases:
    • If the current position is even (even = 0), the function checks whether leading zeros are allowed (leadingZero == 1). If so, it recursively calls f for the next position (idx – 1) with even = 0, leadingZero = 1, and tight as 0 (since a non-zero digit will be used as the leading digit). This is because leading zeros are not allowed in this case.
    • After that, the function iterates over the valid odd digits (1, 3, 5, 7, 9) and checks if each digit is less than or equal to the upper bound (ub) based on the tight flag. If it is, the function recursively calls f for the next position (idx – 1) with even = 1, leadingZero = 0, and tight as the logical AND between the current tight flag and whether the current digit (i) is equal to the upper bound (ub). This ensures that the tightness constraint is maintained as we move to the next position.
  • If the current position is odd (even = 1), the function follows a similar approach but considers even digits (0, 2, 4, 6, 8) instead. It iterates over the valid even digits, checks the upper bound, and makes the recursive call with even = 0.
  • Finally, in the main function, the code reads the range L and R, converts them to strings l and r, and initializes the DP array dp with -1. It then calls the function f twice, once with l and once with r, and subtracts the results to get the count of valid numbers within the range. The result is then printed.
  • Overall, the code uses the concept of digit DP to break down the problem into smaller subproblems and compute the final count efficiently by leveraging memoization.

Explanation of DP States:

dp[idx][even][leadingZero][tight]: This 4-dimensional DP array stores the intermediate results of the recursive function f. It represents the number of valid numbers that can be formed from the remaining digits, given the current state of the computation.
 

  1. idx: Represents the index of the current digit being considered. It ranges from 1 to the number of digits in the input number.
  2. even: Indicates whether the current position is even or odd. It can have two possible values: 0 for even position and 1 for odd position.
  3. leadingZero: Represents whether leading zeros are allowed (1) or not (0).
  4. tight: Indicates whether the current number being formed is still within the range and needs to satisfy the tightness constraint. It can have two possible values: 1 for tight and 0 for non-tight

The DP array is used to avoid recomputing the same subproblem multiple times and improve the efficiency of the solution.

Implementation:

C++




#include <bits/stdc++.h>
using namespace std;
 
long long int dp[20][2][2][2];
 
long long int f(string& nums, long long int idx,
                long long int even, int leadingZero,
                int tight)
{
 
    if (idx == 0) {
        return 1; // Base case: All digits have been
                  // considered, return 1 indicating a valid
                  // number
    }
 
    if (dp[idx][even][leadingZero][tight] != -1) {
        return dp[idx][even][leadingZero]
                 [tight]; // If the subproblem has already
                          // been solved, return the cached
                          // result
    }
 
    long long int cnt = 0;
 
    if (even == 0) {
        // If the current position is even
 
        if (leadingZero == 1) {
            cnt += f(nums, idx - 1, 0, 1,
                     0); // If leading zeros are allowed,
                         // make a recursive call for the
                         // next position with even = 0,
                         // leadingZero = 1, and tight = 0
        }
 
        vector<int> digs = { 1, 3, 5, 7, 9 };
        int ub = (tight == 1)
                     ? (nums[nums.size() - idx] - '0')
                     : 9; // Calculate the upper bound based
                          // on the tight flag and the
                          // current digit
        for (auto i : digs) {
            if (i <= ub) {
                cnt += f(
                    nums, idx - 1, 1, 0,
                    tight
                        & (ub
                           == i)); // Make a recursive call
                                   // for the next position
                                   // with even = 1,
                                   // leadingZero = 0, and
                                   // tight = tight & (ub ==
                                   // i) to maintain the
                                   // tightness constraint
            }
        }
    }
    else {
        // If the current position is odd
 
        vector<int> digs = { 0, 2, 4, 6, 8 };
        int ub = (tight == 1)
                     ? (nums[nums.size() - idx] - '0')
                     : 9; // Calculate the upper bound based
                          // on the tight flag and the
                          // current digit
        for (auto i : digs) {
            if (i <= ub) {
                cnt += f(
                    nums, idx - 1, 0, 0,
                    tight
                        & (i
                           == ub)); // Make a recursive call
                                    // for the next position
                                    // with even = 0,
                                    // leadingZero = 0, and
                                    // tight = tight & (i ==
                                    // ub) to maintain the
                                    // tightness constraint
            }
        }
    }
 
    return dp[idx][even][leadingZero][tight]
           = cnt; // Cache the computed result in the DP
                  // array and return it
}
 
int main()
{
 
    long long int L = 128, R = 162;
    L--;
 
    string l, r;
    l = to_string(L);
    r = to_string(R);
 
    memset(dp, -1,
           sizeof(dp)); // Initialize the DP array with -1
                        // indicating that no subproblem has
                        // been solved yet
    long long int ans1
        = f(l, l.size(), 0, 1,
            1); // Calculate the count for the lower range L
 
    memset(dp, -1, sizeof(dp)); // Reset the DP array
    long long int ans2
        = f(r, r.size(), 0, 1,
            1); // Calculate the count for the upper range R
 
    cout << ans2 - ans1; // Print the difference between the
                         // counts to get the final result
 
    return 0;
}


Java




import java.util.Arrays;
 
public class Main {
 
    static long[][][][] dp;
 
    public static long f(String nums, int idx, int even, int leadingZero, int tight) {
        if (idx == 0) {
            return 1; // Base case: All digits have been considered, return 1 indicating a valid number
        }
 
        if (dp[idx][even][leadingZero][tight] != -1) {
            return dp[idx][even][leadingZero][tight]; // If the subproblem has already been solved, return the cached result
        }
 
        long cnt = 0;
 
        if (even == 0) {
            // If the current position is even
 
            if (leadingZero == 1) {
                cnt += f(nums, idx - 1, 0, 1, 0); // If leading zeros are allowed, make a recursive call for the next position with even = 0, leadingZero = 1, and tight = 0
            }
 
            int[] digs = {1, 3, 5, 7, 9};
            int ub = (tight == 1) ? Character.getNumericValue(nums.charAt(nums.length() - idx)) : 9; // Calculate the upper bound based on the tight flag and the current digit
            for (int i : digs) {
                if (i <= ub) {
                    cnt += f(nums, idx - 1, 1, 0, tight & ((ub == i) ? 1 : 0)); // Make a recursive call for the next position with even = 1, leadingZero = 0, and tight = tight & ((ub == i) ? 1 : 0) to maintain the tightness constraint
                }
            }
        } else {
            // If the current position is odd
 
            int[] digs = {0, 2, 4, 6, 8};
            int ub = (tight == 1) ? Character.getNumericValue(nums.charAt(nums.length() - idx)) : 9; // Calculate the upper bound based on the tight flag and the current digit
            for (int i : digs) {
                if (i <= ub) {
                    cnt += f(nums, idx - 1, 0, 0, tight & ((i == ub) ? 1 : 0)); // Make a recursive call for the next position with even = 0, leadingZero = 0, and tight = tight & ((i == ub) ? 1 : 0) to maintain the tightness constraint
                }
            }
        }
 
        dp[idx][even][leadingZero][tight] = cnt; // Cache the computed result in the DP array
        return cnt;
    }
 
    public static void main(String[] args) {
        long L = 128, R = 162;
        L--;
        String l = Long.toString(L);
        String r = Long.toString(R);
 
        dp = new long[20][2][2][2];
        for (long[][][] arr3D : dp) {
            for (long[][] arr2D : arr3D) {
                for (long[] arr1D : arr2D) {
                    Arrays.fill(arr1D, -1);
                }
            }
        }
 
        long ans1 = f(l, l.length(), 0, 1, 1); // Calculate the count for the lower range L
 
        dp = new long[20][2][2][2];
        for (long[][][] arr3D : dp) {
            for (long[][] arr2D : arr3D) {
                for (long[] arr1D : arr2D) {
                    Arrays.fill(arr1D, -1);
                }
            }
        }
 
        long ans2 = f(r, r.length(), 0, 1, 1); // Calculate the count for the upper range R
 
        System.out.println(ans2 - ans1); // Print the difference between the counts to get the final result
    }
}


Python3




dp = [[[[ -1 for _ in range(2)] for _ in range(2)] for _ in range(2)] for _ in range(20)]
 
def f(nums, idx, even, leadingZero, tight):
    if idx == 0:
        return 1  # Base case: All digits have been considered, return 1 indicating a valid number
 
    if dp[idx][even][leadingZero][tight] != -1:
        return dp[idx][even][leadingZero][tight]  # If the subproblem has already been solved, return the cached result
 
    cnt = 0
 
    if even == 0:
        # If the current position is even
 
        if leadingZero == 1:
            cnt += f(nums, idx - 1, 0, 1, 0# If leading zeros are allowed, make a recursive call for the next position with even = 0, leadingZero = 1, and tight = 0
 
        digs = [1, 3, 5, 7, 9]
        ub = int(nums[len(nums) - idx]) if tight == 1 else 9  # Calculate the upper bound based on the tight flag and the current digit
        for i in digs:
            if i <= ub:
                cnt += f(nums, idx - 1, 1, 0, tight & (ub == i))  # Make a recursive call for the next position with even = 1, leadingZero = 0, and tight = tight & (ub == i) to maintain the tightness constraint
 
    else:
        # If the current position is odd
 
        digs = [0, 2, 4, 6, 8]
        ub = int(nums[len(nums) - idx]) if tight == 1 else 9  # Calculate the upper bound based on the tight flag and the current digit
        for i in digs:
            if i <= ub:
                cnt += f(nums, idx - 1, 0, 0, tight & (i == ub))  # Make a recursive call for the next position with even = 0, leadingZero = 0, and tight = tight & (i == ub) to maintain the tightness constraint
 
    dp[idx][even][leadingZero][tight] = cnt  # Cache the computed result in the DP array
    return cnt
 
 
L, R = 128, 162
l = str(L - 1)
r = str(R)
 
dp = [[[[ -1 for _ in range(2)] for _ in range(2)] for _ in range(2)] for _ in range(20)]  # Initialize the DP array with -1 indicating that no subproblem has been solved yet
ans1 = f(l, len(l), 0, 1, 1# Calculate the count for the lower range L
 
dp = [[[[ -1 for _ in range(2)] for _ in range(2)] for _ in range(2)] for _ in range(20)]  # Reset the DP array
ans2 = f(r, len(r), 0, 1, 1# Calculate the count for the upper range R
 
print(ans2 - ans1)  # Print the difference between the counts to get the final result


C#




// C# code for above approach :
using System;
using System.Collections.Generic;
 
public class Program
{
    static long[,,,] dp = new long[20, 2, 2, 2];
 
    static long f(string nums, int idx, int even, int leadingZero, int tight)
    {
        if (idx == 0)
        {
            return 1; // Base case: All digits have been considered, return 1 indicating a valid number
        }
 
        if (dp[idx, even, leadingZero, tight] != -1)
        {
            return dp[idx, even, leadingZero, tight]; // If the subproblem has already been solved, return the cached result
        }
 
        long cnt = 0;
 
        if (even == 0)
        {
            // If the current position is even
            if (leadingZero == 1)
            {
                cnt += f(nums, idx - 1, 0, 1, 0); // If leading zeros are allowed, make a recursive call for the next position with even = 0, leadingZero = 1, and tight = 0
            }
 
            List<int> digs = new List<int> { 1, 3, 5, 7, 9 };
            int ub = (tight == 1) ? (nums[nums.Length - idx] - '0') : 9; // Calculate the upper bound based on the tight flag and the current digit
 
            foreach (var i in digs)
            {
                if (i <= ub)
                {
                    cnt += f(nums, idx - 1, 1, 0, tight & (ub == i ? 1 : 0)); // Make a recursive call for the next position with even = 1, leadingZero = 0, and tight = tight & (ub == i) to maintain the tightness constraint
                }
            }
        }
        else
        {
            // If the current position is odd
            List<int> digs = new List<int> { 0, 2, 4, 6, 8 };
            int ub = (tight == 1) ? (nums[nums.Length - idx] - '0') : 9; // Calculate the upper bound based on the tight flag and the current digit
 
            foreach (var i in digs)
            {
                if (i <= ub)
                {
                    cnt += f(nums, idx - 1, 0, 0, tight & (i == ub ? 1 : 0)); // Make a recursive call for the next position with even = 0, leadingZero = 0, and tight = tight & (i == ub) to maintain the tightness constraint
                }
            }
        }
 
        return dp[idx, even, leadingZero, tight] = cnt; // Cache the computed result in the DP array and return it
    }
 
    public static void Main(string[] args)
    {
        long L = 128, R = 162;
        L--;
 
        string l = L.ToString();
        string r = R.ToString();
 
        for (int i = 0; i < 20; i++)
        {
            for (int j = 0; j < 2; j++)
            {
                for (int k = 0; k < 2; k++)
                {
                    for (int m = 0; m < 2; m++)
                    {
                        dp[i, j, k, m] = -1; // Initialize the DP array with -1 indicating that no subproblem has been solved yet
                    }
                }
            }
        }
 
        long ans1 = f(l, l.Length, 0, 1, 1); // Calculate the count for the lower range L
 
        for (int i = 0; i < 20; i++)
        {
            for (int j = 0; j < 2; j++)
            {
                for (int k = 0; k < 2; k++)
                {
                    for (int m = 0; m < 2; m++)
                    {
                        dp[i, j, k, m] = -1; // Reset the DP array
                    }
                }
            }
        }
 
        long ans2 = f(r, r.Length, 0, 1, 1); // Calculate the count for the upper range R
 
        Console.WriteLine(ans2 - ans1); // Print the difference between the counts to get the final result
    }
}
 
//this code is contributed by uttamdp_10


Javascript




let dp = [...Array(20)].map(() => [...Array(2)].map(() => [...Array(2)].map(() => Array(2).fill(-1))));
 
function f(nums, idx, even, leadingZero, tight) {
    if (idx === 0) {
        return 1; // Base case: All digits have been considered, return 1 indicating a valid number
    }
 
    if (dp[idx][even][leadingZero][tight] !== -1) {
        return dp[idx][even][leadingZero][tight]; // If the subproblem has already been solved, return the cached result
    }
 
    let cnt = 0;
 
    if (even === 0) {
        // If the current position is even
 
        if (leadingZero === 1) {
            cnt += f(nums, idx - 1, 0, 1, 0); // If leading zeros are allowed, make a recursive call for the next position with even = 0, leadingZero = 1, and tight = 0
        }
 
        let digs = [1, 3, 5, 7, 9];
        let ub = (tight === 1) ? parseInt(nums[nums.length - idx]) : 9; // Calculate the upper bound based on the tight flag and the current digit
        for (let i of digs) {
            if (i <= ub) {
                cnt += f(nums, idx - 1, 1, 0, tight & (ub === i)); // Make a recursive call for the next position with even = 1, leadingZero = 0, and tight = tight & (ub === i) to maintain the tightness constraint
            }
        }
 
    } else {
        // If the current position is odd
 
        let digs = [0, 2, 4, 6, 8];
        let ub = (tight === 1) ? parseInt(nums[nums.length - idx]) : 9; // Calculate the upper bound based on the tight flag and the current digit
        for (let i of digs) {
            if (i <= ub) {
                cnt += f(nums, idx - 1, 0, 0, tight & (i === ub)); // Make a recursive call for the next position with even = 0, leadingZero = 0, and tight = tight & (i === ub) to maintain the tightness constraint
            }
        }
    }
 
    dp[idx][even][leadingZero][tight] = cnt; // Cache the computed result in the DP array
    return cnt;
}
 
let L = 128, R = 162;
let l = (L - 1).toString();
let r = R.toString();
 
dp = [...Array(20)].map(() => [...Array(2)].map(() => [...Array(2)].map(() => Array(2).fill(-1)))); // Initialize the DP array with -1 indicating that no subproblem has been solved yet
let ans1 = f(l, l.length, 0, 1, 1); // Calculate the count for the lower range L
 
dp = [...Array(20)].map(() => [...Array(2)].map(() => [...Array(2)].map(() => Array(2).fill(-1)))); // Reset the DP array
let ans2 = f(r, r.length, 0, 1, 1); // Calculate the count for the upper range R
 
console.log(ans2 - ans1); // Print the difference between the counts to get the final result


Output

7

Time Complexity: O(log(R) * 2 * 2 * 2) = O(log(R)), where R is the value of the upper range.
Auxiliary Space: O(log(R) * 2 * 2 * 2) = O(log(R)), where R is the value of the upper range.



Last Updated : 17 Aug, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads