Count N digits numbers with sum divisible by K
Last Updated :
15 Nov, 2023
Given two integers N and K, the task is to count all N digits numbers whose sum of digits is divisible by K.
Examples:
Input: N = 2, K = 7
Output: 12
Explanation: 2 digits numbers with sum divisible by 7 are: {16, 25, 34, 43, 52, 59, 61, 68, 70, 77, 86, 95}.
Therefore, the required output is 12.
Input: N = 1, K = 2
Output: 4
Naive Approach: The simplest approach is to traverse all the numbers from the range [10(N - 1), 10N - 1] and check if the sum of all the digits of a number that lies within the range is divisible by K or not. For every number for which the condition is found to be true, increase count. Finally, print the count.
Time Complexity: O(10N - 10N - 1 - 1)
Auxiliary Space: O(1)
Efficient Approach: The idea is to use Digit DP technique to optimize the above approach. Below is the recurrence relation:
CountNum(N, sum, st) = \sum^{9}_{i=0} countNum(N - 1, (sum + i)\mod K, st)
sum: represents sum of digits
st: check if a number contains any leading 0.
Follow the steps below to solve the problem:
- Initialize a 3D array dp[N][K][st] to compute and store the values of all subproblems of the above recurrence relation.
- Finally, return the value of dp[N][sum%K][st].
C++
// C++ Program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
#define M 1000
// Function to count the N digit numbers
// whose sum is divisible by K
int countNum(int N, int sum, int K,
bool st, int dp[M][M][2])
{
// Base case
if (N == 0 and sum == 0) {
return 1;
}
if (N < 0) {
return 0;
}
// If already computed
// subproblem occurred
if (dp[N][sum][st] != -1) {
return dp[N][sum][st];
}
// Store the count of N digit numbers
// whose sum is divisible by K
int res = 0;
// Check if the number does not contain
// any leading 0.
int start = st == 1 ? 0 : 1;
// Recurrence relation
for (int i = start; i <= 9; i++) {
res += countNum(N - 1, (sum + i) % K,
K, (st | i > 0), dp);
}
return dp[N][sum][st] = res;
}
// Driver Code
int main()
{
int N = 2, K = 7;
// Stores the values of
// overlapping subproblems
int dp[M][M][2];
memset(dp, -1, sizeof(dp));
cout << countNum(N, 0, K, 0, dp);
}
Java
// Java program to implement
// the above approach
import java.util.*;
import java.lang.*;
class GFG {
static final int M = 1000;
// Function to count the N digit numbers
// whose sum is divisible by K
static int countNum(int N, int sum, int K,
int st, int dp[][][])
{
// Base case
if (N == 0 && sum == 0) {
return 1;
}
if (N < 0) {
return 0;
}
// If already computed
// subproblem occurred
if (dp[N][sum][st] != -1) {
return dp[N][sum][st];
}
// Store the count of N digit numbers
// whose sum is divisible by K
int res = 0;
// Check if the number does not contain
// any leading 0.
int start = st == 1 ? 0 : 1;
// Recurrence relation
for (int i = start; i <= 9; i++) {
res += countNum(N - 1, (sum + i) % K,
K, ((st | i) > 0) ? 1 : 0, dp);
}
return dp[N][sum][st] = res;
}
// Driver code
public static void main(String[] args)
{
int N = 2, K = 7;
// Stores the values of
// overlapping subproblems
int[][][] dp = new int[M][M][2];
for (int[][] i : dp)
for (int[] j : i)
Arrays.fill(j, -1);
System.out.print(countNum(N, 0, K, 0, dp));
}
}
// This code is contributed by offbeat
Python3
# Python3 program to implement
# the above approach
# Function to count the N digit
# numbers whose sum is divisible by K
def countNum(N, sum, K, st, dp):
# Base case
if (N == 0 and sum == 0):
return 1
if (N < 0):
return 0
# If already computed
# subproblem occurred
if (dp[N][sum][st] != -1):
return dp[N][sum][st]
# Store the count of N digit
# numbers whose sum is divisible by K
res = 0
start = 1
# Check if the number does not contain
# any leading 0.
if (st == 1):
start = 0
else:
start = 1
# Recurrence relation
for i in range(start, 10):
min = 0
if ((st | i) > 0):
min = 1
else:
min = 0
res += countNum(N - 1, (sum + i) % K,
K, min, dp)
dp[N][sum][st] = res
return dp[N][sum][st]
# Driver code
if __name__ == '__main__':
N = 2
K = 7
M = 100
# Stores the values of
# overlapping subproblems
dp = [[[-1 for i in range(2)]
for j in range(M)]
for j in range(M)]
print(countNum(N, 0, K, 0, dp))
# This code is contributed by shikhasingrajput
C#
// C# program to implement
// the above approach
using System;
class GFG{
static int M = 1000;
// Function to count the N digit numbers
// whose sum is divisible by K
static int countNum(int N, int sum, int K,
int st, int[,, ] dp)
{
// Base case
if (N == 0 && sum == 0)
{
return 1;
}
if (N < 0)
{
return 0;
}
// If already computed
// subproblem occurred
if (dp[N, sum, st] != -1)
{
return dp[N, sum, st];
}
// Store the count of N digit numbers
// whose sum is divisible by K
int res = 0;
// Check if the number does not contain
// any leading 0.
int start = (st == 1 ? 0 : 1);
// Recurrence relation
for(int i = start; i <= 9; i++)
{
res += countNum(N - 1, (sum + i) % K,
K, ((st | i) > 0) ? 1 : 0, dp);
}
return dp[N, sum, st] = res;
}
// Driver code
static public void Main()
{
int N = 2, K = 7;
// Stores the values of
// overlapping subproblems
int[,, ] dp = new int[M, M, 2];
for(int i = 0; i < M; i++)
for(int j = 0; j < M; j++)
for(int k = 0; k < 2; k++)
dp[i, j, k] = -1;
Console.WriteLine(countNum(N, 0, K, 0, dp));
}
}
// This code is contributed by offbeat
JavaScript
<script>
// JavaScript Program to implement
// the above approach
var M = 1000;
// Function to count the N digit numbers
// whose sum is divisible by K
function countNum(N, sum, K, st, dp)
{
// Base case
if (N == 0 && sum == 0) {
return 1;
}
if (N < 0) {
return 0;
}
// If already computed
// subproblem occurred
if (dp[N][sum][st] != -1) {
return dp[N][sum][st];
}
// Store the count of N digit numbers
// whose sum is divisible by K
var res = 0;
// Check if the number does not contain
// any leading 0.
var start = st == 1 ? 0 : 1;
// Recurrence relation
for (var i = start; i <= 9; i++) {
res += countNum(N - 1, (sum + i) % K,
K, (st | i > 0), dp);
}
return dp[N][sum][st] = res;
}
// Driver Code
var N = 2, K = 7;
// Stores the values of
// overlapping subproblems
var dp = Array.from(Array(M), ()=>Array(M));
for(var i =0; i<M; i++)
for(var j =0; j<M; j++)
dp[i][j] = new Array(2).fill(-1);
document.write( countNum(N, 0, K, 0, dp));
</script>
Time Complexity:O(10*N*K)
Auxiliary Space: O(N*K)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a table 3D DP table to store the solution of the subproblems which is of length N * K * 2 (true , false) .
- Initialize the table with base cases
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
- Return the final solution stored in dp[N][sum][1] + dp[N][sum][0] .
Implementation :
C++
// C++ program for above approach
#include <bits/stdc++.h>
using namespace std;
// Function to count the N digit numbers
// whose sum is divisible by K
int countNum(int N, int sum, int K) {
// initialize DP to Store computations of subproblems
int dp[N + 1][K][2];
memset(dp, 0, sizeof(dp)); // fill DP with 0
// Base case
dp[0][0][0] = 1;
// Iterate over subproblems and get the solution
// of current problem with the help of recursion
for (int i = 1; i <= N; i++) {
for (int j = 0; j < K; j++) {
for (int k = (i == 1); k <= 9; k++) { // skip leading zeroes
int rem = (j - k % K + K) % K;
// get current value from previous computation
dp[i][j][1] += dp[i - 1][rem][1];
if (k > 0)
dp[i][j][1] += dp[i - 1][rem][0];
else
dp[i][j][0] += dp[i - 1][rem][0];
}
}
}
// return answer
return dp[N][sum][1] + dp[N][sum][0];
}
// Drivre Code
int main() {
int N = 2, K = 7;
// function call
cout << countNum(N, 0, K) << endl;
return 0;
}
// this code is contributed by bhardwajji
Java
import java.util.*;
public class Main {
// Function to count the N digit numbers
// whose sum is divisible by K
public static int countNum(int N, int sum, int K) {
// initialize DP to Store computations of subproblems
int[][][] dp = new int[N + 1][K][2];
for (int[][] row : dp)
for (int[] innerRow : row)
Arrays.fill(innerRow, 0); // fill DP with 0
// Base case
dp[0][0][0] = 1;
// Iterate over subproblems and get the solution
// of current problem with the help of recursion
for (int i = 1; i <= N; i++) {
for (int j = 0; j < K; j++) {
for (int k = (i == 1 ? 1 : 0); k <= 9; k++) { // skip leading zeroes
int rem = (j - k % K + K) % K;
// get current value from previous computation
dp[i][j][1] += dp[i - 1][rem][1];
if (k > 0)
dp[i][j][1] += dp[i - 1][rem][0];
else
dp[i][j][0] += dp[i - 1][rem][0];
}
}
}
// return answer
return dp[N][sum][1] + dp[N][sum][0];
}
// Driver Code
public static void main(String[] args) {
int N = 2, K = 7;
// function call
System.out.println(countNum(N, 0, K));
}
}
Python3
def count_num(n, sum_, k):
# initialize DP to Store computations of subproblems
dp = [[[0] * 2 for _ in range(k)] for _ in range(n + 1)]
# Base case
dp[0][0][0] = 1
# Iterate over subproblems and get the solution
# of current problem with the help of recursion
for i in range(1, n + 1):
for j in range(k):
for l in range(10):
if i == 1 and l == 0:
continue
rem = (j - l % k + k) % k
# get current value from previous computation
dp[i][j][1] += dp[i - 1][rem][1]
if l > 0:
dp[i][j][1] += dp[i - 1][rem][0]
else:
dp[i][j][0] += dp[i - 1][rem][0]
# return answer
return dp[n][sum_][1] + dp[n][sum_][0]
# Drivre Code
if __name__ == '__main__':
n = 2
k = 7
# function call
print(count_num(n, 0, k))
C#
using System;
class GFG {
// Function to count the N digit numbers
// whose sum is divisible by K
static int countNum(int N, int sum, int K)
{
// initialize DP to Store computations of
// subproblems
int[, , ] dp = new int[N + 1, K, 2];
Array.Clear(dp, 0, dp.Length); // fill DP with 0
// Base case
dp[0, 0, 0] = 1;
// Iterate over subproblems and get the solution
// of current problem with the help of recursion
for (int i = 1; i <= N; i++) {
for (int j = 0; j < K; j++) {
for (int k = (i == 1 ? 1 : 0); k <= 9;
k++) // skip leading zeroes
{
int rem = (j - k % K + K) % K;
// get current value from previous
// computation
dp[i, j, 1] += dp[i - 1, rem, 1];
if (k > 0)
dp[i, j, 1] += dp[i - 1, rem, 0];
else
dp[i, j, 0] += dp[i - 1, rem, 0];
}
}
}
// return answer
return dp[N, sum, 1] + dp[N, sum, 0];
}
// Drivre Code
static void Main()
{
int N = 2;
int K = 7;
Console.WriteLine(countNum(N, 0, K));
}
}
JavaScript
function countNum(N, sum, K) {
// initialize DP to Store computations of subproblems
let dp = new Array(N + 1);
for (let i = 0; i <= N; i++) {
dp[i] = new Array(K);
for (let j = 0; j < K; j++) {
dp[i][j] = new Array(2).fill(0);
}
}
// Base case
dp[0][0][0] = 1;
// Iterate over subproblems and get the solution
// of current problem with the help of recursion
for (let i = 1; i <= N; i++) {
for (let j = 0; j < K; j++) {
for (let k = (i == 1 ? 1 : 0); k <= 9; k++) { // skip leading zeroes
let rem = (j - k % K + K) % K;
// get current value from previous computation
dp[i][j][1] += dp[i - 1][rem][1];
if (k > 0)
dp[i][j][1] += dp[i - 1][rem][0];
else
dp[i][j][0] += dp[i - 1][rem][0];
}
}
}
// return answer
return dp[N][sum][1] + dp[N][sum][0];
}
// Driver Code
let N = 2, K = 7;
console.log(countNum(N, 0, K));
Time Complexity: O(10*N*K)
Auxiliary Space: O(N*K)
Optmized approach: Using DP Tabulation method (Iterative approach) with Space Optimization
The approach to solve this problem remains the same, but we will utilize DP tabulation (bottom-up) method with a space-efficient optimization using "prev" and "curr" arrays.
Steps to solve this problem using space optimization:
- Create two 2D arrays: "prev" and "curr", each of length [K][2].
- Initialize the "prev" array with base cases.
- Iterate over the subproblems to compute the current problem's value using the previous computations stored in the "prev" array.
- Update the "curr" array with the calculated values for the current iteration.
- Copy the values of the "curr" array to the "prev" array, and reset the "curr" array to all zeros for the next iteration.
- Finally, return the final solution stored in prev[sum][1] + prev[sum][0].
Below is the implementation of the above approach:
C++
// C++ implementation of space optmized approach
#include <bits/stdc++.h>
using namespace std;
int countNum(int N, int sum, int K)
{
int prev[K][2] = { 0 };
int curr[K][2] = { 0 };
// Base case
prev[0][0] = 1;
for (int i = 1; i <= N; i++) {
for (int j = 0; j < K; j++) {
for (int k = (i == 1); k <= 9;
k++) { // skip leading zeroes
int rem = (j - k % K + K) % K;
curr[j][1] += prev[rem][1];
if (k > 0)
curr[j][1] += prev[rem][0];
else
curr[j][0] += prev[rem][0];
}
}
// Copy curr to prev for the next iteration
for (int j = 0; j < K; j++) {
prev[j][0] = curr[j][0];
prev[j][1] = curr[j][1];
curr[j][0] = 0;
curr[j][1] = 0;
}
}
return prev[sum][1] + prev[sum][0];
}
int main()
{
int N = 2, K = 7;
cout << countNum(N, 0, K) << endl;
return 0;
}
// This code is contributed by Tapesh(tapeshdua420)
Java
// Java implementation of space optimized approach
import java.util.*;
class Main {
public static int countNum(int N, int sum, int K) {
int[][] prev = new int[K][2];
int[][] curr = new int[K][2];
// Base case
prev[0][0] = 1;
for (int i = 1; i <= N; i++) {
for (int j = 0; j < K; j++) {
for (int k = (i == 1) ? 1 : 0; k <= 9; k++) { // skip leading zeroes
int rem = (j - k % K + K) % K;
curr[j][1] += prev[rem][1];
if (k > 0)
curr[j][1] += prev[rem][0];
else
curr[j][0] += prev[rem][0];
}
}
// Copy curr to prev for the next iteration
for (int j = 0; j < K; j++) {
prev[j][0] = curr[j][0];
prev[j][1] = curr[j][1];
curr[j][0] = 0;
curr[j][1] = 0;
}
}
return prev[sum][1] + prev[sum][0];
}
public static void main(String[] args) {
int N = 2, K = 7;
System.out.println(countNum(N, 0, K));
}
}
// This code is contributed by Tapesh(tapeshdua420)
Python3
# Python implementation:
def countNum(N, sum, K):
prev = [[0, 0] for _ in range(K)]
curr = [[0, 0] for _ in range(K)]
# Base case
prev[0][0] = 1
for i in range(1, N+1):
for j in range(K):
for k in range(int(i == 1), 10): # skip leading zeroes
rem = (j - k % K + K) % K
curr[j][1] += prev[rem][1]
if k > 0:
curr[j][1] += prev[rem][0]
else:
curr[j][0] += prev[rem][0]
# Copy curr to prev for the next iteration
for j in range(K):
prev[j][0] = curr[j][0]
prev[j][1] = curr[j][1]
curr[j][0] = 0
curr[j][1] = 0
return prev[sum][1] + prev[sum][0]
N = 2
K = 7
print(countNum(N, 0, K))
# This code is contributed by Tapesh(tapeshdu420)
C#
// C# implementation
using System;
class MainClass {
public static int CountNum(int N, int sum, int K) {
int[,] prev = new int[K, 2];
int[,] curr = new int[K, 2];
// Base case
prev[0, 0] = 1;
for (int i = 1; i <= N; i++) {
for (int j = 0; j < K; j++) {
for (int k = (i == 1) ? 1 : 0; k <= 9; k++) { // skip leading zeroes
int rem = (j - k % K + K) % K;
curr[j, 1] += prev[rem, 1];
if (k > 0)
curr[j, 1] += prev[rem, 0];
else
curr[j, 0] += prev[rem, 0];
}
}
// Copy curr to prev for the next iteration
for (int j = 0; j < K; j++) {
prev[j, 0] = curr[j, 0];
prev[j, 1] = curr[j, 1];
curr[j, 0] = 0;
curr[j, 1] = 0;
}
}
return prev[sum, 1] + prev[sum, 0];
}
public static void Main(string[] args) {
int N = 2, K = 7;
Console.WriteLine(CountNum(N, 0, K));
}
}
// This code is contributed by Sakshi
JavaScript
function countNum(N, sum, K) {
const prev = new Array(K).fill(0).map(() => new Array(2).fill(0));
const curr = new Array(K).fill(0).map(() => new Array(2).fill(0));
// Base case
prev[0][0] = 1;
for (let i = 1; i <= N; i++) {
for (let j = 0; j < K; j++) {
for (let k = (i === 1) ? 1 : 0; k <= 9; k++) { // skip leading zeroes
const rem = (j - (k % K) + K) % K;
curr[j][1] += prev[rem][1];
if (k > 0) {
curr[j][1] += prev[rem][0];
} else {
curr[j][0] += prev[rem][0];
}
}
}
// Copy curr to prev for the next iteration
for (let j = 0; j < K; j++) {
prev[j][0] = curr[j][0];
prev[j][1] = curr[j][1];
curr[j][0] = 0;
curr[j][1] = 0;
}
}
return prev[sum][1] + prev[sum][0];
}
const N = 2;
const K = 7;
console.log(countNum(N, 0, K));
// This code is contributed by shivamgupta0987654321
Time Complexity: O(10*N*K)
Auxiliary Space: O(K)
Similar Reads
Count the numbers with N digits and whose suffix is divisible by K Given two positive integers n and k, the task is to count the number of positive integers d such that d has n digits and any of the suffixes of its decimal representation is divisible by k. Examples: Input: n = 1, k = 2 Output: 4 Explanation: There are 4 such integers in which any of the suffix is d
12 min read
Count n digit numbers divisible by given number Given number of digit n and a number, the task is to count all the numbers which are divisible by that number and having n digit. Examples : Input : n = 2, number = 7Output : 13Explanation: There are nine n digit numbers that are divisible by 7. Numbers are 14, 21, 28, 35, 42, 49, .... 91, 98 Input
8 min read
Counting numbers with given digits and digit sum Given a number N, count the numbers X of length exactly N such that the number X and the sum of digits of the number X have digits A and B only in their decimal representation. The length of a number is defined as the number of digits in its decimal representation without leading zeroes. Note: As th
11 min read
Count of N digit palindromic numbers divisible by 9 Given an integer N, the task is to count the number of N digit palindromic numbers containing digits from 1 to 9 and divisible by 9. Examples: Input: N = 1 Output: 1 Explanation: Only 9 is 1 digit number which is palindrome and divisible by 9.Input: N = 3 Output: 9 Explanation: Three digit numbers t
4 min read
Smallest K digit number divisible by X Integers X and K are given. The task is to find the smallest K-digit number divisible by X. Examples : Input : X = 83, K = 5 Output : 10043 10040 is the smallest 5 digit number that is multiple of 83. Input : X = 5, K = 2 Output : 10Recommended PracticeSmallest K digit number divisible by XTry It! A
4 min read