# Count numbers with exactly K non-zero digits and distinct odd digit sum

• Last Updated : 15 Jun, 2021

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

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.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

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: 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++

 // C++ program to Count the numbers having// exactly K non-zero digits and sum// of digits are odd and distinct.#include using namespace std; // To store digits of Nvector<int> digits; // visited mapbool vis = { false }; // DP Tableint dp; // Push all the digits of N into// digits vectorvoid ConvertIntoDigit(int n){    while (n) {        int dig = n % 10;        digits.push_back(dig);        n /= 10;    }    reverse(digits.begin(), digits.end());} // Function returns the countint 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        else            cnt += solve(idx + 1, k, newtight,                         sum + i);    }     // Memoize and return    return dp[idx][k][tight][sum] = cnt;} // Driver codeint 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    ConvertIntoDigit(N);     // We keep record of 0s we need to    // place in the number    k = digits.size() - k;    cout << solve(0, k, 0, 0);}

## Java

 // Java program to count the numbers having// exactly K non-zero digits and sum// of digits are odd and distinct.import java.util.*; class GFG{ // To store digits of Nstatic Vector digits = new Vector(); // visited mapstatic boolean []vis = new boolean; // DP Tablestatic int [][][][]dp = new int; // Push all the digits of N into// digits vectorstatic void ConvertIntoDigit(int n){    while (n > 0)    {        int dig = n % 10;        digits.add(dig);        n /= 10;    }    Collections.reverse(digits);} // Function returns the countstatic 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 % 2 == 1)    {                 // If it is not present in map,        // mark it as true and return 1        if (!vis[sum])        {            vis[sum] = true;            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] > 0)    {        return dp[idx][k][tight][sum];    }     // Upper limit    int j;    if (idx < digits.size() && tight == 0)    {        j = digits.get(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 ? 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 codepublic static void main(String[] args){     // 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    ConvertIntoDigit(N);     // We keep record of 0s we need to    // place in the number    k = digits.size() - k;         System.out.print(solve(0, k, 0, 0));}} // This code is contributed by amal kumar choubey

## Python3

 # Python3 program to Count the numbers having# exactly K non-zero digits and sum# of digits are odd and distinct.  # To store digits of Ndigits = []  # visited mapvis = [False for i in range(170)]  # DP Tabledp = [[[[0 for l in range(170)] for k in range(2)] for j in range(19)] for i in range(19)]  # Push all the digits of N into# digits vectordef ConvertIntoDigit(n):     while (n > 0):        dig = n % 10;        digits.append(dig);        n //= 10;    digits.reverse()     # Function returns the countdef solve(idx, k, tight, sum):     # If desired number is formed    # whose sum is odd    if (idx == len(digits) and k == 0 and sum % 2 == 1):                 # If it is not present in map,        # mark it as true and return 1        if (not vis[sum]):            vis[sum] = True;            return 1;                 # Sum is present in map already        return 0;         # Desired result not found    if (idx > len(digits)):        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    j = 0;    if (idx<len(digits) and tight == 0):        j = digits[idx];         else:        j = 9;         # To store the count of    # desired numbers    cnt = 0;      # If k is non-zero, i ranges from    # 0 to j else [1, j]    for i in range(0 if k else 1, j + 1):        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);         dp[idx][k][tight][sum] = cnt         # Memoize and return    return cnt; # Driver codeif __name__=='__main__':      # K is the number of exact non-zero    # elements to have in number    N = 169    k = 2;      # break N into its digits    ConvertIntoDigit(N);      # We keep record of 0s we need to    # place in the number    k = len(digits) - k;    print(solve(0, k, 0, 0)) # This code is contributed by rutvik_56.

## C#

 // C# program to count the numbers having// exactly K non-zero digits and sum// of digits are odd and distinct.using System;using System.Collections.Generic; class GFG{ // To store digits of Nstatic List<int> digits = new List<int>(); // visited mapstatic bool []vis = new bool; // DP Tablestatic int [,,,]dp = new int[ 19, 19, 2, 170 ]; // Push all the digits of N into// digits vectorstatic void ConvertIntoDigit(int n){    while (n > 0)    {        int dig = n % 10;        digits.Add(dig);        n /= 10;    }    digits.Reverse();} // Function returns the countstatic int solve(int idx, int k,                 int tight, int sum){         // If desired number is formed    // whose sum is odd    if (idx == digits.Count &&          k == 0 && sum % 2 == 1)    {                 // If it is not present in map,        // mark it as true and return 1        if (!vis[sum])        {            vis[sum] = true;            return 1;        }                 // Sum is present in map already        return 0;    }     // Desired result not found    if (idx > digits.Count)    {        return 0;    }     // If that state is already calculated    // just return that state value    if (dp[idx, k, tight, sum] > 0)    {        return dp[idx, k, tight, sum];    }     // Upper limit    int j;    if (idx < digits.Count && 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 ? 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 codepublic static void Main(String[] args){         // 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    ConvertIntoDigit(N);     // We keep record of 0s we need to    // place in the number    k = digits.Count - k;         Console.Write(solve(0, k, 0, 0));}} // This code is contributed by amal kumar choubey

## Javascript

 
Output:
12

My Personal Notes arrow_drop_up