Count numbers in given range such that sum of even digits is greater than sum of odd digits
Given two integers L and R denoting a range [L, R]. The task is to find the total count of numbers in the given range [L,R] whose sum of even digits is greater than the sum of odd digits.
Examples:
Input : L=2 R=10
Output : 4
Numbers having the property that sum of even
digits is greater than sum of odd digits are: 2, 4, 6, 8
Input : L=2 R=17
Output : 7
Prerequisites: Digit-DP
Approach:
Firstly, count the required numbers up to R i.e. in the range [0, R]. To reach the answer in the range [L, R] solve for the range from zero to R and then subtracting the answer for the range from zero to L – 1. Define the DP states as follows:
- Consider the number as a sequence of digits, one state is the position at which we are currently at. This position can have values from 0 to 18 if we are dealing with the numbers up to 10^18. In each recursive call, try to build the sequence from left to right by placing a digit from 0 to 9.
- First state is the sum of the even digits that has been placed so far.
- Second state is the sum of the odd digits that has been placed so far.
- Another state is the boolean variable tight which tells the number we are trying to build has already become smaller than R so that in the upcoming recursive calls we can place any digit from 0 to 9. If the number has not become smaller, the maximum limit of digit we can place is the digit at the current position in R.
Below is the implementation of the above approach:
C++
// C++ code to count number in the range // having the sum of even digits greater // than the sum of odd digits #include <bits/stdc++.h> // as the number can be up to 10^18 #define int long long using namespace std; vector< int > v; int dp[18][180][180][2]; int memo( int index, int evenSum, int oddSum, int tight) { // Base Case if (index == v.size()) { // check if condition satisfied or not if (evenSum > oddSum) return 1; else return 0; } // If this result is already computed // simply return it if (dp[index][evenSum][oddSum][tight] != -1) return dp[index][evenSum][oddSum][tight]; // Maximum limit upto which we can place // digit. If tight is 0, means number has // already become smaller so we can place // any digit, otherwise num[pos] int limit = (tight) ? v[index] : 9; int ans = 0; for ( int d = 0; d <= limit; d++) { int currTight = 0; if (d == v[index]) currTight = tight; // if current digit is odd if (d % 2 != 0) ans += memo(index + 1, evenSum, oddSum + d, currTight); // if current digit is even else ans += memo(index + 1, evenSum + d, oddSum, currTight); } dp[index][evenSum][oddSum][tight] = ans; return ans; } // Function to convert n into its // digit vector and uses memo() function // to return the required count int CountNum( int n) { v.clear(); while (n) { v.push_back(n % 10); n = n / 10; } reverse(v.begin(), v.end()); // Initialize DP memset (dp, -1, sizeof (dp)); return memo(0, 0, 0, 1); } // Driver Code int32_t main() { int L, R; L = 2; R = 10; cout << CountNum(R) - CountNum(L - 1) << "\n" ; return 0; } |
Java
// Java code to count number in the range // having the sum of even digits greater // than the sum of odd digits import java.util.*; class GFG { static Vector<Integer> v = new Vector<>(); static int [][][][] dp = new int [ 18 ][ 180 ][ 180 ][ 2 ]; static int memo( int index, int evenSum, int oddSum, int tight) { // Base Case if (index == v.size()) { // check if condition satisfied or not if (evenSum > oddSum) { return 1 ; } else { return 0 ; } } // If this result is already computed // simply return it if (dp[index][evenSum][oddSum][tight] != - 1 ) { return dp[index][evenSum][oddSum][tight]; } // Maximum limit upto which we can place // digit. If tight is 0, means number has // already become smaller so we can place // any digit, otherwise num[pos] int limit = (tight > 0 ) ? v.get(index) : 9 ; int ans = 0 ; for ( int d = 0 ; d <= limit; d++) { int currTight = 0 ; if (d == v.get(index)) { currTight = tight; } // if current digit is odd if (d % 2 != 0 ) { ans += memo(index + 1 , evenSum, oddSum + d, currTight); } // if current digit is even else { ans += memo(index + 1 , evenSum + d, oddSum, currTight); } } dp[index][evenSum][oddSum][tight] = ans; return ans; } // Function to convert n into its // digit vector and uses memo() function // to return the required count static int CountNum( int n) { v.clear(); while (n > 0 ) { v.add(n % 10 ); n = n / 10 ; } Collections.reverse(v); // Initialize DP for ( int i = 0 ; i < 18 ; i++) { for ( int j = 0 ; j < 180 ; j++) { for ( int k = 0 ; k < 180 ; k++) { for ( int l = 0 ; l < 2 ; l++) { dp[i][j][k][l] = - 1 ; } } } } return memo( 0 , 0 , 0 , 1 ); } // Driver Code public static void main(String[] args) { int L, R; L = 2 ; R = 10 ; System.out.println(CountNum(R) - CountNum(L - 1 )); } } // This code is contributed by Princi Singh |
Python3
# Python code to count number in the range # having the sum of even digits greater # than the sum of odd digits def memo(index, evenSum, oddSum, tight): # Base Case if index = = len (v): # check if condition satisfied or not if evenSum > oddSum: return 1 else : return 0 # If this result is already computed # simply return it if dp[index][evenSum][oddSum][tight] ! = - 1 : return dp[index][evenSum][oddSum][tight] # Maximum limit upto which we can place # digit. If tight is 0, means number has # already become smaller so we can place # any digit, otherwise num[index] limit = v[index] if tight else 9 ans = 0 for d in range (limit + 1 ): currTight = 0 if d = = v[index]: currTight = tight # if current digit is odd if d % 2 ! = 0 : ans + = memo(index + 1 , evenSum, oddSum + d, currTight) # if current digit is even else : ans + = memo(index + 1 , evenSum + d, oddSum, currTight) dp[index][evenSum][oddSum][tight] = ans return ans # Function to convert n into its digit vector # and uses memo() function to return the # required count def countNum(n): global dp, v v.clear() num = [] while n: v.append(n % 10 ) n / / = 10 v.reverse() # Initialize dp dp = [[[[ - 1 , - 1 ] for i in range ( 180 )] for j in range ( 180 )] for k in range ( 18 )] return memo( 0 , 0 , 0 , 1 ) # Driver Code if __name__ = = "__main__" : dp = [] v = [] L = 2 R = 10 print (countNum(R) - countNum(L - 1 )) # This code is contributed by # sanjeev2552 |
C#
// C# code to count number in the range // having the sum of even digits greater // than the sum of odd digits using System.Collections.Generic; using System; class GFG { static List< int > v = new List< int >(); static int [,,,]dp = new int [18,180,180,2]; static int memo( int index, int evenSum, int oddSum, int tight) { // Base Case if (index == v.Count) { // check if condition satisfied or not if (evenSum > oddSum) { return 1; } else { return 0; } } // If this result is already computed // simply return it if (dp[index,evenSum,oddSum,tight] != -1) { return dp[index,evenSum,oddSum,tight]; } // Maximum limit upto which we can place // digit. If tight is 0, means number has // already become smaller so we can place // any digit, otherwise num[pos] int limit = (tight > 0) ? v[index] : 9; int ans = 0; for ( int d = 0; d <= limit; d++) { int currTight = 0; if (d == v[index]) { currTight = tight; } // if current digit is odd if (d % 2 != 0) { ans += memo(index + 1, evenSum, oddSum + d, currTight); } // if current digit is even else { ans += memo(index + 1, evenSum + d, oddSum, currTight); } } dp[index,evenSum,oddSum,tight] = ans; return ans; } // Function to convert n into its // digit vector and uses memo() function // to return the required count static int CountNum( int n) { v.Clear(); while (n > 0) { v.Add(n % 10); n = n / 10; } v.Reverse(); // Initialize DP for ( int i = 0; i < 18; i++) { for ( int j = 0; j < 180; j++) { for ( int k = 0; k < 180; k++) { for ( int l = 0; l < 2; l++) { dp[i,j,k,l] = -1; } } } } return memo(0, 0, 0, 1); } // Driver Code public static void Main(String[] args) { int L, R; L = 2; R = 10; Console.WriteLine(CountNum(R) - CountNum(L - 1)); } } /* This code is contributed by PrinciRaj1992 */ |
4
Time Complexity : There would be at max 18*(180)*(180)*2 computations when 0 < a,b < 1018
Recommended Posts:
- Count of numbers between range having only non-zero digits whose sum of digits is N and number is divisible by M
- Count of numbers from range [L, R] whose sum of digits is Y
- Count of Numbers in Range where the number does not contain more than K non zero digits
- Count of all even numbers in the range [L, R] whose sum of digits is divisible by 3
- Count numbers in range L-R that are divisible by all of its non-zero digits
- Count Numbers in Range with difference between Sum of digits at even and odd positions as Prime
- Count of integers in a range which have even number of odd digits and odd number of even digits
- Total numbers with no repeated digits in a range
- Numbers of Length N having digits A and B and whose sum of digits contain only digits A and B
- Numbers with sum of digits equal to the sum of digits of its all prime factor
- Count numbers with same first and last digits
- Count different numbers possible using all the digits their frequency times
- Count of n digit numbers whose sum of digits equals to given sum
- Count different numbers that can be generated such that there digits sum is equal to 'n'
- Count numbers formed by given two digit with sum having given digits
If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.