Related Articles

Related Articles

Count of integers in a range which have even number of odd digits and odd number of even digits
  • Difficulty Level : Expert
  • Last Updated : 13 Feb, 2020

Given a range [L, R], the task is to count the numbers which have even number of odd digits and odd number of even digits. For example,

  1. 8 has 1 even digit and 0 odd digit – Satisfies the condition since 1 is odd and 0 is even.
  2. 545 has 1 even digit and 2 odd digits – Satisfies the condition since 1 is odd and 2 is even.
  3. 4834 has 3 even digits and 1 odd digit – Does not satisfy the condition since there are odd numbers(i.e 1) of odd digits.

Examples:

Input: L = 1, R = 9
Output: 4
2, 4, 6 and 8 are the only integers from the
given range that satisfy the given conditions.

Input: L = 1, R = 19
Output: 4

Input: L = 123, R = 984
Output: 431



Approach:

  • Case 1
    There is a pattern in which these numbers occur between 1 and 10^{k} (where 1<=k<=18).
    Number of occurrences from

    • 1 – 10 and 1 – 100 are 4
    • 1 – 1000 and 1 – 10000 are 454
    • 1 – 10000 and 1 – 100000 are 45454

    and so on…

  • Case 2
    • If the number of digits in a number is even then it cannot satisfy the given condition because we need an odd number(of digits) and an even number(of digits) to satisfy our condition and odd number + even number is always odd
    • So if the number of digits for a given number(say n) is even then its number of occurrences from 1 is equal to the number of occurrences from 1 to largest 10^{k} (1<=k<=18) which is less than n
    • Example:
      Let n = 19, number of digits in 19 are 2
      Therefore number of occurrences from 1 – 19 = number of occurrences from 1 – 10 (since 10 the largest 10^{k} less than 19)

  • Case 3
    If number of digits for a given number(say n) are odd then number of occurrences between 10^{k}+1 and n is equal to

    where 10^{i} is the largest 10^{k} less than n.

Implementation: Now we now how to calculate the number of occurrences from 1 to given n. Therefore,
Number of occurrences from L to R = NumberOfOccurrencesUpto(R) – NumberOfOccurrencesUpto(L – 1) where L is not equal to 1.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
#define ll long long
  
// Pattern table from Case 1
map<ll, ll> values{{1, 0},
                   {10, 4},
                   {100, 4},
                   {1000, 454},
                   {10000, 454},
                   {100000, 45454},
                   {1000000, 45454},
                   {10000000, 4545454},
                   {100000000, 4545454},
                   {1000000000, 454545454},
                   {10000000000, 454545454},
                   {100000000000, 45454545454},
                   {1000000000000, 45454545454},
                   {10000000000000, 4545454545454},
                   {100000000000000, 4545454545454},
                   {1000000000000000, 454545454545454},
                   {10000000000000000, 454545454545454},
                   {100000000000000000, 45454545454545454},
                   {1000000000000000000, 45454545454545454}};
  
// Function that returns the number of
// even and odd digits in val
pair<ll, ll> count_even_odd(ll val) 
{
    ll even = 0, odd = 0;
    while (val) 
    {
        ll num = val % 10;
        if (num % 2 == 0)
            even++;
        else
            odd++;
        val /= 10;
    }
    return make_pair(even, odd);
}
  
// Function that returns True if num
// satisfies the given condition
bool satisfies_condition(ll num) 
{
    pair<ll, ll> answer = count_even_odd(num);
    ll even = answer.first;
    ll odd = answer.second;
  
    if (even % 2 == 1 and 
         odd % 2 == 0) return true;
    return false;
}
  
// Function to return the count of 
// numbers from 1 to val that 
// satisfies the given condition
ll count_upto(ll val)
{
    // If the value is already present
    // in the values dict
    if (values.find(val) != values.end()) 
        return values[val];
  
    ll index = 1;
    for (int i = 0; 
             i < to_string(val).length() - 1; 
             i++) 
         index *= 10;
  
    // If the value is even
    // Case 2
    if (to_string(val).length() % 2 == 0) 
        return values[index];
  
    ll val_len = to_string(val).length();
    ll cnt = values[index];
  
    // Now the problem is to count the desired
    // numbers from 10**(val_len-1) + 1 to val
    ll left_end = index + 1;
  
    // Case 3
    // Eliminating all the even numbers
    cnt += (val - left_end) / 2;
    if (satisfies_condition(val) or 
        satisfies_condition(left_end)) 
        cnt++;
  
    return cnt;
}
  
// Driver Code
int main() 
{
    // Input l and r
    ll l = 123, r = 984;
    ll right = count_upto(r);
    ll left = 0;
  
    if (l == '1')
        left = 0;
    else
        left = count_upto(l - 1);
  
    cout << right - left << endl;
    return 0;
}
  
// This code is contributed by
// sanjeev2552

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation of the approach
  
# Pattern table from Case 1
values = {
    1: 0,
    10: 4,
    100: 4,
    1000: 454,
    10000: 454,
    100000: 45454,
    1000000: 45454,
    10000000: 4545454,
    100000000: 4545454,
    1000000000: 454545454,
    10000000000: 454545454,
    100000000000: 45454545454,
    1000000000000: 45454545454,
    10000000000000: 4545454545454,
    100000000000000: 4545454545454,
    1000000000000000: 454545454545454,
    10000000000000000: 454545454545454,
    100000000000000000: 45454545454545454,
    1000000000000000000: 45454545454545454,
}
  
# Function that returns the number of 
# even and odd digits in val
def count_even_odd(val):
    even = odd = 0
    while val > 0:
        num = val % 10
        if num % 2 == 0:
            even += 1
        else:
            odd += 1
        val //= 10
  
    return even, odd
  
# Function that returns True if num 
# satisfies the given condition
def satisfies_condition(num):
    even, odd = count_even_odd(num)
    if even % 2 == 1 and odd % 2 == 0:
        return True
    return False
  
  
# Function to return the count of numbers 
# from 1 to val that satisfies the given condition
def count_upto(val):
  
    # If the value is already present in the
    # values dict
    if int(val) in values:
        return values[int(val)]
  
    # If the value is even
    # Case 2
    if len(val) % 2 == 0:
        return values[int('1' + '0' * (len(val) - 1))]
  
    val_len = len(val)
    count = values[int('1' + '0' * (val_len - 1))]
  
    # Now the problem is to count the desired
    # numbers from 10**(val_len-1) + 1 to val
    left_end = int('1' + '0' * (val_len - 1)) + 1
  
    # Case 3
    # Eliminating all the even numbers
    count += (int(val) - left_end) // 2
  
    if satisfies_condition(int(val)) or satisfies_condition(left_end):
        count += 1
    return count
  
  
if __name__ == '__main__':
  
    # Input L and R ( as a string )
    l, r = '123', '984'
  
    right = count_upto(r)
  
    left = 0
    if(l == '1'):
        left = 0
    else:
        left = count_upto(str(int(l)-1))
  
    print(right - left)

chevron_right


Output:

431

Time Complexity: O(logn)

competitive-programming-img




My Personal Notes arrow_drop_up
Recommended Articles
Page :