Count numbers with exactly K non-zero 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.


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: Digit-DP

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:

  1. We can use Dynamic Programming and it’s very useful technique that is digit-dp to solve this problem.
  2. So instead of keeping a record of non-zero 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.
  3. We keep all the digits of N into a vector say, digits.
  4. 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 Non-zero 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.
  5. Now, also take a parameter that is sum, which will calculate the sum of digits of a number till the base case hits successfully.
  6. Also, a boolean map is used which will store all the odd sums calculated already, so it gives distinct odd sums.
  7. The recurrence will be:

       f(idx, K, tight, sum) = $\sum_{i=0}^{j} f(idx+1, K-1, newtight, sum+i)   f(idx, K, tight, sum) = $\sum_{i=1}^{j} f(idx+1, K, newtight, sum+i)

    where j = digits[idx] if tight = 0, else j = 9

  8. 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.

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 non-zero 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;
        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 non-zero, 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
            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 non-zero
    // elements to have in number
    int N, k;
    N = 169, k = 2;
    // break N into its digits
    // We keep record of 0s we need to
    // place in the number
    k = digits.size() - k;
    cout << solve(0, k, 0, 0);




Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up

Recommended Posts:

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using or mail your article to 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.