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

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:

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++ 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 N  vector<int> digits;     // visited map  bool vis = { false };     // DP Table  int dp;     // 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 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 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      ConvertIntoDigit(N);         // We keep record of 0s we need to      // place in the number      k = digits.size() - k;      cout << solve(0, k, 0, 0);  }

Output:

12


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 Check out this Author's contributed articles.

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.