Count numbers with exactly K nonzero digits and distinct odd digit sum
Given an Integer N, and a number K, the task is to find out the total numbers from 0 to N which have exactly K non zero digits and the sum of those digits should be odd and that sum should be distinct. The number N can be as large as 10^18.
Examples:
Input : N = 10, K = 1
Output : 5
The numbers which follow the conditions are >
1, 3, 5, 7 and 9
The digit sum of 10 that is (1+0) = 1 is also odd, but 1 is already included in our count.Input : N = 100, K = 2
Output : 8
Prerequisites: DigitDP
Naive Approach:
A naive approach for linear traversing in O(N) of all elements from 0 to N and calculating sum of digits in log(n) where n is the number of digits in that number will fail for large inputs of N.
Efficient Approach:
 We can use Dynamic Programming and it’s very useful technique that is digitdp to solve this problem.
 So instead of keeping a record of nonzero integers, we keep a record of zeroes we can keep at different indices, idx in variable K. The number of zeroes we can keep can be found initially by subtracting K with the number of digits in N.
 We keep all the digits of N into a vector say, digits.

Now, we calculate range of elements we can keep at index idx by analysing K.
 Suppose at index idx, we are left with K = 1 (A Nonzero value), then our range to put elements is [0, j] where j is the upper bound decided by the tight value obtained from the current index of the digit from vector digits.
 If at idx, we are left with K = 0, then our range becomes [1, j] because we can’t put in 0 there.
 Now, also take a parameter that is sum, which will calculate the sum of digits of a number till the base case hits successfully.
 Also, a boolean map is used which will store all the odd sums calculated already, so it gives distinct odd sums.

The recurrence will be:
where j = digits[idx] if tight = 0, else j = 9

Base Case:

When idx = digits.size(), K == 0 and sum is odd.
We mark the sum as true and return 1 else return 0.  If idx > digits.size() then return 0.

When idx = digits.size(), K == 0 and sum is odd.
So we create a DP table say DP[idx][K][tight][sum] which will store our result from the recurrence above and return the count by memoizing it to this DP table.
Below is the implementation of the above approach:
// C++ program to Count the numbers having // exactly K nonzero digits and sum // of digits are odd and distinct. #include <bits/stdc++.h> using namespace std; // To store digits of N vector< int > digits; // visited map bool vis[170] = { false }; // DP Table int dp[19][19][2][170]; // Push all the digits of N into // digits vector void ConvertIntoDigit( int n) { while (n) { int dig = n % 10; digits.push_back(dig); n /= 10; } reverse(digits.begin(), digits.end()); } // Function returns the count int solve( int idx, int k, int tight, int sum) { // If desired number is formed // whose sum is odd if (idx == digits.size() && k == 0 && sum & 1) { // If it is not present in map, // mark it as true and return 1 if (!vis[sum]) { vis[sum] = 1; return 1; } // Sum is present in map already return 0; } // Desired result not found if (idx > digits.size()) { return 0; } // If that state is already calculated // just return that state value if (dp[idx][k][tight][sum]) { return dp[idx][k][tight][sum]; } // Upper limit int j; if (tight == 0) { j = digits[idx]; } else { j = 9; } // To store the count of // desired numbers int cnt = 0; // If k is nonzero, i ranges from // 0 to j else [1, j] for ( int i = (k ? 0 : 1); i <= j; i++) { int newtight = tight; if (i < j) { newtight = 1; } // If current digit is 0, decrement // k and recurse sum is not changed // as we are just adding 0 that // makes no difference if (i == 0) cnt += solve(idx + 1, k  1, newtight, sum); // If i is non zero, then k remains // unchanged and value is added to sum else cnt += solve(idx + 1, k, newtight, sum + i); } // Memoize and return return dp[idx][k][tight][sum] = cnt; } // Driver code int main() { // K is the number of exact nonzero // elements to have in number int N, k; N = 169, k = 2; // break N into its digits ConvertIntoDigit(N); // We keep record of 0s we need to // place in the number k = digits.size()  k; cout << solve(0, k, 0, 0); } 
12
Don’t stop now and take your learning to the next level. Learn all the important concepts of Data Structures and Algorithms with the help of the most trusted course: DSA Self Paced. Become industry ready at a studentfriendly price.
Recommended Posts:
 Count of Ndigit numbers with all distinct digits
 Count numbers whose maximum sum of distinct digitsum is less than or equals M
 Count numbers less than N containing digits from the given set : Digit DP
 Count numbers formed by given two digit with sum having given digits
 Count of n digit numbers whose sum of digits equals to given sum
 Count total number of N digit numbers such that the difference between sum of even and odd digits is 1
 Count of Ndigit numbers with absolute difference of adjacent digits not exceeding K
 Count of Numbers in Range where first digit is equal to last digit of the number
 Check if all subnumbers have distinct Digit product
 Count numbers in a range with digit sum divisible by K having first and last digit different
 Numbers having Unique (or Distinct) digits
 Count distinct pairs from two arrays having same sum of digits
 N digit numbers divisible by 5 formed from the M digits
 Print all ndigit numbers whose sum of digits equals to given sum
 Count of numbers upto N digits formed using digits 0 to K1 without any adjacent 0s
 Count of numbers between range having only nonzero digits whose sum of digits is N and number is divisible by M
 Sum of all N digit palindromic numbers divisible by 9 formed using digits 1 to 9
 Print all ndigit numbers with absolute difference between sum of even and odd digits is 1
 Count positive integers with 0 as a digit and maximum 'd' digits
 Count numbers in given range such that sum of even digits is greater than sum of odd 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.