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: 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: 
 
- We can use Dynamic Programming and it’s very useful technique that is digit-dp to solve this problem. 
 - 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. 
 - 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 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. 
 
 - 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. 
 - 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++
// 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 Nvector<int> digits;// visited mapbool vis[170] = { false };// DP Tableint dp[19][19][2][170];// 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<Integer> digits = new Vector<Integer>();// visited mapstatic boolean []vis = new boolean[170];// 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;    }    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[170];// 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
<script>    // JavaScript program to count the numbers having    // exactly K non-zero digits and sum    // of digits are odd and distinct.         // To store digits of N    let digits = [];    // visited map    let vis = new Array(170);    vis.fill(false);    // DP Table    let dp = new Array(19);    for(let i = 0; i < 19; i++)    {        dp[i] = new Array(19);        for(let j = 0; j < 19; j++)        {            dp[i][j] = new Array(2);            for(let k = 0; k < 2; k++)            {                dp[i][j][k] = new Array(170);                for(let l = 0; l < 170; l++)                {                    dp[i][j][k][l] = 0;                }            }        }    }    // Push all the digits of N into    // digits vector    function ConvertIntoDigit(n)    {        while (n > 0)        {            let dig = n % 10;            digits.push(dig);            n = parseInt(n / 10, 10);        }        digits.reverse();    }    // Function returns the count    function solve(idx, k, tight, sum)    {        // If desired number is formed        // whose sum is odd        if (idx == digits.length &&              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.length)        {            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        let j;        if (idx < digits.length && tight == 0)        {            j = digits[idx];        }        else        {            j = 9;        }        // To store the count of        // desired numbers        let cnt = 0;        // If k is non-zero, i ranges from        // 0 to j else [1, j]        for(let i = (k > 0 ? 0 : 1); i <= j; i++)        {            let 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        dp[idx][k][tight][sum] = cnt;        return dp[idx][k][tight][sum];    }         // K is the number of exact non-zero    // elements to have in number    let 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.length - k;          document.write(solve(0, k, 0, 0));</script> | 
12
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

                                    