Given a string consisting of digits 0-9, count the number of subsequences in it divisible by m.
Examples:
Input : str = "1234", n = 4
Output : 4
The subsequences 4, 12, 24 and 124 are
divisible by 4.
Input : str = "330", n = 6
Output : 4
The subsequences 30, 30, 330 and 0 are
divisible by n.
Input : str = "676", n = 6
Output : 3
The subsequences 6, 6 and 66
This problem can be recursively defined. Let the remainder of a string with value x be ‘r’ when divided by n. Adding one more character to this string changes its remainder to (r*10 + newdigit) % n. For every new character, we have two choices, either add it in all current subsequences or ignore it. Thus, we have an optimal substructure. The following shows the brute force version of this:
string str = "330";
int n = 6
// idx is value of current index in str
// rem is current remainder
int count(int idx, int rem)
{
// If last character reached
if (idx == n)
return (rem == 0)? 1 : 0;
int ans = 0;
// we exclude it, thus remainder
// remains the same
ans += count(idx+1, rem);
// we include it and thus new remainder
ans += count(idx+1, (rem*10 + str[idx]-'0')%n);
return ans;
}
The above recursive solution has overlapping subproblems as shown in below recursion tree.
input string = "330"
(0,0) ===> at 0th index with 0 remainder
(exclude 0th / (include 0th character)
character) /
(1,0) (1,3) ======> at index 1 with 3 as
(E)/ (I) /(E) the current remainder
(2,0) (2,3) (2,3)
|-------|
These two subproblems overlap
Thus, we can apply Dynamic Programming. Below is the implementation.
C++
#include<bits/stdc++.h>
using namespace std;
int countDivisibleSubseq(string str, int n)
{
int len = str.length();
int dp[len][n];
memset (dp, 0, sizeof (dp));
dp[0][(str[0]- '0' )%n]++;
for ( int i=1; i<len; i++)
{
dp[i][(str[i]- '0' )%n]++;
for ( int j=0; j<n; j++)
{
dp[i][j] += dp[i-1][j];
dp[i][(j*10 + (str[i]- '0' ))%n] += dp[i-1][j];
}
}
return dp[len-1][0];
}
int main()
{
string str = "1234" ;
int n = 4;
cout << countDivisibleSubseq(str, n);
return 0;
}
|
Java
class GFG {
static int countDivisibleSubseq(String str, int n) {
int len = str.length();
int dp[][] = new int [len][n];
dp[ 0 ][(str.charAt( 0 ) - '0' ) % n]++;
for ( int i = 1 ; i < len; i++) {
dp[i][(str.charAt(i) - '0' ) % n]++;
for ( int j = 0 ; j < n; j++) {
dp[i][j] += dp[i - 1 ][j];
dp[i][(j * 10 + (str.charAt(i) - '0' )) % n] += dp[i - 1 ][j];
}
}
return dp[len - 1 ][ 0 ];
}
public static void main(String[] args) {
String str = "1234" ;
int n = 4 ;
System.out.print(countDivisibleSubseq(str, n));
}
}
|
Python 3
def countDivisibleSubseq( str , n):
l = len ( str )
dp = [[ 0 for x in range (l)]
for y in range (n)]
dp[ int ( str [ 0 ]) % n][ 0 ] + = 1
for i in range ( 1 , l):
dp[ int ( str [i]) % n][i] + = 1
for j in range (n):
dp[j][i] + = dp[j][i - 1 ]
dp[(j * 10 + int ( str [i])) % n][i] + = dp[j][i - 1 ]
return dp[ 0 ][l - 1 ]
if __name__ = = "__main__" :
str = "1234"
n = 4
print (countDivisibleSubseq( str , n))
|
C#
using System;
class GFG {
static int countDivisibleSubseq( string str, int n) {
int len = str.Length;
int [,] dp = new int [len,n];
dp[0,(str[0] - '0' ) % n]++;
for ( int i = 1; i < len; i++) {
dp[i,(str[i] - '0' ) % n]++;
for ( int j = 0; j < n; j++) {
dp[i,j] += dp[i - 1,j];
dp[i,(j * 10 + (str[i] - '0' )) % n] += dp[i - 1,j];
}
}
return dp[len - 1,0];
}
public static void Main() {
String str = "1234" ;
int n = 4;
Console.Write(countDivisibleSubseq(str, n));
}
}
|
Javascript
<script>
function countDivisibleSubseq(str,n)
{
let len = str.length;
let dp = new Array(len);
for (let i = 0; i < len; i++)
{
dp[i] = new Array(n);
for (let j = 0; j < n; j++)
{
dp[i][j] = 0;
}
}
dp[0][(str[0] - '0' ) % n]++;
for (let i = 1; i < len; i++) {
dp[i][(str[i] - '0' ) % n]++;
for (let j = 0; j < n; j++) {
dp[i][j] += dp[i - 1][j];
dp[i][(j * 10 + (str[i] - '0' )) % n] += dp[i - 1][j];
}
}
return dp[len - 1][0];
}
let str = "1234" ;
let n = 4;
document.write(countDivisibleSubseq(str, n));
</script>
|
Time Complexity: O(len * n)
Auxiliary Space : O(len * n)
Efficient approach : Space optimization
In previous approach the dp[i][j] is depend upon the current and previous row of 2D matrix. So to optimize space we use two vectors temp and dp that keep track of current and previous row of DP.
Implementation Steps:
- The countDivisibleSubseq function counts the number of subsequences in a given string str that are divisible by a given number n.
- It initializes an array dp of size n to store counts.
- It iterates through each digit of the string and updates the counts in dp based on remainders.
- At each iteration, it considers the current digit and the previous counts to calculate the updated counts.
- Finally, it returns the count of subsequences divisible by n stored in dp[0].
Implementation:
C++
#include<bits/stdc++.h>
using namespace std;
int countDivisibleSubseq(string str, int n)
{
int len = str.length();
int dp[n];
memset (dp, 0, sizeof (dp));
dp[(str[0]- '0' )%n]++;
for ( int i=1; i<len; i++)
{
int temp[n];
memset (temp, 0, sizeof (temp));
temp[(str[i]- '0' )%n]++;
for ( int j=0; j<n; j++)
{
temp[j] += dp[j];
temp[(j*10 + (str[i]- '0' ))%n] += dp[j];
}
for ( int j=0; j<n; j++)
{
dp[j] = temp[j];
}
}
return dp[0];
}
int main()
{
string str = "1234" ;
int n = 4;
cout << countDivisibleSubseq(str, n);
return 0;
}
|
Java
public class GFG {
public static int countDivisibleSubseq(String str, int n) {
int length = str.length();
int [] dp = new int [n];
dp[Integer.parseInt(String.valueOf(str.charAt( 0 ))) % n] += 1 ;
for ( int i = 1 ; i < length; i++) {
int [] temp = new int [n];
temp[Integer.parseInt(String.valueOf(str.charAt(i))) % n] += 1 ;
for ( int j = 0 ; j < n; j++) {
temp[j] += dp[j];
int newRemainder = (j * 10 + Integer.parseInt(String.valueOf(str.charAt(i)))) % n;
temp[newRemainder] += dp[j];
}
dp = temp;
}
return dp[ 0 ];
}
public static void main(String[] args) {
String str = "1234" ;
int n = 4 ;
System.out.println(countDivisibleSubseq(str, n));
}
}
|
Python3
def countDivisibleSubseq( str , n):
length = len ( str )
dp = [ 0 ] * n
dp[ int ( str [ 0 ]) % n] + = 1
for i in range ( 1 , length):
temp = [ 0 ] * n
temp[ int ( str [i]) % n] + = 1
for j in range (n):
temp[j] + = dp[j]
new_remainder = (j * 10 + int ( str [i])) % n
temp[new_remainder] + = dp[j]
dp = temp
return dp[ 0 ]
str = "1234"
n = 4
print (countDivisibleSubseq( str , n))
|
C#
using System;
class GFG {
static int CountDivisibleSubseq( string str, int n)
{
int len = str.Length;
int [] dp = new int [n];
Array.Fill(dp, 0);
dp[(str[0] - '0' )
% n]++;
for ( int i = 1; i < len; i++) {
int [] temp = new int [n];
Array.Fill(temp, 0);
temp[(str[i] - '0' )
% n]++;
for ( int j = 0; j < n; j++) {
temp[j] += dp[j];
temp[(j * 10 + (str[i] - '0' )) % n]
+= dp[j];
}
for ( int j = 0; j < n; j++) {
dp[j] = temp[j];
}
}
return dp[0];
}
static void Main()
{
string str = "1234" ;
int n = 4;
Console.WriteLine(CountDivisibleSubseq(str, n));
}
}
|
Javascript
function countDivisibleSubseq(str, n) {
const len = str.length;
const dp = new Array(n).fill(0);
dp[Number(str[0]) % n]++;
for (let i = 1; i < len; i++) {
const temp = new Array(n).fill(0);
temp[Number(str[i]) % n]++;
for (let j = 0; j < n; j++) {
temp[j] += dp[j];
temp[(j * 10 + Number(str[i])) % n] += dp[j];
}
for (let j = 0; j < n; j++) {
dp[j] = temp[j];
}
}
return dp[0];
}
const str = "1234" ;
const n = 4;
console.log(countDivisibleSubseq(str, n));
|
Time Complexity: O(len * n)
Auxiliary Space : O(n)
This article is contributed by Ekta Goel. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or if you want to share more information about the topic discussed above.