Number of substrings divisible by 8 but not by 3
Given a string of digits “0-9”. The task is to find the number of substrings which are divisible by 8 but not by 3.
Examples :
Input : str = "888"
Output : 5
Substring indexes : (1, 1), (1, 2), (2, 2),
(2, 3), (3, 3).
Input : str = "6564525600"
Output : 15
A number is divisible by 3 if sum of its digits is divisible by 3. And the number is divisible by 8 if last three digits are divisible by 8. Now, the idea is to store the prefix sum of the string i.e. count of prefixes such that sum of the digits of the prefix modulo 3 is either 0, 1, 2.
Next we iterate over the string and for each position i, count the number of substrings ending at i and divisible by 8. From this value, we subtract the number of substrings ending at i and divisible by 3. We define a |S| X 3 size 2D array, |S| is size of string, say dp[i][j]. dp[i][j] can be define as at any index i, number of substring starting from index 0 to index i having output j when digits from index 0 are added upto index i and modulo 3. Therefore 0 <= j <= 2, since modulo 3.
Now, we will iterate over string and check each one digit number, two digit number and three digit number which are divisible by 8. For one digit, just check if character at index is 8 or not. For two digit, check whether it is divisible by 8 and not divisible by 3. For three digit, form the number and check if it is divisible by 8 or not. If the number is divisible then last three digits must be divisible by 8.
So all the substrings ending at this index must be divisible by 8 i.e. (i-3) substrings. But it will also contain those substrings which are divisible by 3, so simply remove them using dp[i][j].
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define MAX 1000
int count( char s[], int len)
{
int cur = 0, dig = 0;
int sum[MAX], dp[MAX][3];
memset (sum, 0, sizeof (sum));
memset (dp, 0, sizeof (dp));
dp[0][0] = 1;
for ( int i = 1; i <= len; i++)
{
dig = int (s[i-1])-48;
cur += dig;
cur %= 3;
sum[i] = cur;
dp[i][0] = dp[i-1][0];
dp[i][1] = dp[i-1][1];
dp[i][2] = dp[i-1][2];
dp[i][sum[i]]++;
}
int ans = 0, dprev = 0, value = 0, dprev2 = 0;
for ( int i = 1; i <= len; i++)
{
dig = int (s[i-1])-48;
if (dig == 8)
ans++;
if (i-2 >= 0)
{
dprev = int (s[i-2])-48;
value = dprev*10 + dig;
if ((value%8 == 0) && (value%3 != 0))
ans++;
}
if (i-3 >= 0)
{
dprev2 = int (s[i-3])-48;
dprev = int (s[i-2])-48;
value = dprev2*100 + dprev*10 + dig;
if (value%8 != 0)
continue ;
ans += (i-2);
ans -= (dp[i-3][sum[i]]);
}
}
return ans;
}
int main()
{
char str[] = "6564525600" ;
int len = strlen (str);
cout << count(str, len) <<endl;
return 0;
}
|
Java
import java.io.*;
class GFG
{
static int count(String s, int len)
{
int MAX = 1000 ;
int cur = 0 , dig = 0 ;
int [] sum = new int [MAX];
int [][] dp = new int [MAX][ 3 ];
dp[ 0 ][ 0 ] = 1 ;
for ( int i = 1 ; i <= len; i++)
{
dig = ( int )(s.charAt(i- 1 )) - 48 ;
cur += dig;
cur %= 3 ;
sum[i] = cur;
dp[i][ 0 ] = dp[i- 1 ][ 0 ];
dp[i][ 1 ] = dp[i- 1 ][ 1 ];
dp[i][ 2 ] = dp[i- 1 ][ 2 ];
dp[i][sum[i]]++;
}
int ans = 0 , dprev = 0 , value = 0 , dprev2 = 0 ;
for ( int i = 1 ; i <= len; i++)
{
dig = ( int )(s.charAt(i- 1 )) - 48 ;
if (dig == 8 )
ans++;
if (i- 2 >= 0 )
{
dprev = ( int )(s.charAt(i- 2 )) - 48 ;
value = dprev* 10 + dig;
if ((value% 8 == 0 ) && (value% 3 != 0 ))
ans++;
}
if (i- 3 >= 0 )
{
dprev2 = ( int )(s.charAt(i- 3 )) - 48 ;
dprev = ( int )(s.charAt(i- 2 )) - 48 ;
value = dprev2* 100 + dprev* 10 + dig;
if (value% 8 != 0 )
continue ;
ans += (i- 2 );
ans -= (dp[i- 3 ][sum[i]]);
}
}
return ans;
}
public static void main (String[] args)
{
String str = "6564525600" ;
int len = str.length();
System.out.println(count(str, len));
}
}
|
Python3
def count(s, Len ):
global MAX
cur = 0
dig = 0
Sum = [ 0 ] * MAX
dp = [[ 0 , 0 , 0 ] for i in range ( MAX )]
dp[ 0 ][ 0 ] = 1
for i in range ( 1 , Len + 1 ):
dig = int (s[i - 1 ]) - 48
cur + = dig
cur % = 3
Sum [i] = cur
dp[i][ 0 ] = dp[i - 1 ][ 0 ]
dp[i][ 1 ] = dp[i - 1 ][ 1 ]
dp[i][ 2 ] = dp[i - 1 ][ 2 ]
dp[i][ Sum [i]] + = 1
ans = 0
dprev = 0
value = 0
dprev2 = 0
for i in range ( 1 , Len + 1 ):
dig = int (s[i - 1 ]) - 48
if dig = = 8 :
ans + = 1
if i - 2 > = 0 :
dprev = int (s[i - 2 ]) - 48
value = dprev * 10 + dig
if (value % 8 = = 0 ) and (value % 3 ! = 0 ):
ans + = 1
if i - 3 > = 0 :
dprev2 = int (s[i - 3 ]) - 48
dprev = int (s[i - 2 ]) - 48
value = (dprev2 * 100 +
dprev * 10 + dig)
if value % 8 ! = 0 :
continue
ans + = (i - 2 )
ans - = (dp[i - 3 ][ Sum [i]])
return ans
MAX = 1000
Str = "6564525600"
Len = len ( Str )
print (count( Str , Len ))
|
C#
using System;
class GFG
{
static int count(String s, int len)
{
int MAX = 1000;
int cur = 0, dig = 0;
int [] sum = new int [MAX];
int [,] dp = new int [MAX,3];
dp[0, 0] = 1;
for ( int i = 1; i <= len; i++)
{
dig = ( int )(s[i-1]) - 48;
cur += dig;
cur %= 3;
sum[i] = cur;
dp[i, 0] = dp[i-1, 0];
dp[i, 1] = dp[i-1, 1];
dp[i, 2] = dp[i-1, 2];
dp[i, sum[i]]++;
}
int ans = 0, dprev = 0, value = 0, dprev2 = 0;
for ( int i = 1; i <= len; i++)
{
dig = ( int )(s[i-1]) - 48;
if (dig == 8)
ans++;
if (i-2 >= 0)
{
dprev = ( int )(s[i-2]) - 48;
value = dprev*10 + dig;
if ((value % 8 == 0) && (value % 3 != 0))
ans++;
}
if (i - 3 >= 0)
{
dprev2 = ( int )(s[i-3]) - 48;
dprev = ( int )(s[i-2]) - 48;
value = dprev2 * 100 + dprev * 10 + dig;
if (value % 8 != 0)
continue ;
ans += (i - 2);
ans -= (dp[i - 3,sum[i]]);
}
}
return ans;
}
public static void Main (String[] args)
{
String str = "6564525600" ;
int len = str.Length;
Console.Write(count(str, len));
}
}
|
Javascript
<script>
let MAX = 1000
function count(s, Len){
let cur = 0
let dig = 0
let Sum = new Array(MAX).fill(0)
let dp = new Array(MAX);
for (let i=0;i<MAX;i++){
dp[i] = [0, 0, 0]
}
dp[0][0] = 1
for (let i=1;i<Len + 1;i++){
dig = s.charCodeAt(i - 1) - '0' .charCodeAt(0)
cur += dig
cur %= 3
Sum[i] = cur
dp[i][0] = dp[i - 1][0]
dp[i][1] = dp[i - 1][1]
dp[i][2] = dp[i - 1][2]
dp[i][Sum[i]] += 1
}
let ans = 0
let dprev = 0
let value = 0
let dprev2 = 0
for (let i=1;i<Len + 1;i++){
dig = s.charCodeAt(i - 1) - '0' .charCodeAt(0)
if (dig == 8)
ans += 1
if (i - 2 >= 0){
dprev = s.charCodeAt(i - 2) - '0' .charCodeAt(0)
value = dprev * 10 + dig
if ((value % 8 == 0) && (value % 3 != 0))
ans += 1
}
if (i - 3 >= 0){
dprev2 = s.charCodeAt(i - 3) - '0' .charCodeAt(0)
dprev = s.charCodeAt(i - 2) - '0' .charCodeAt(0)
value = (dprev2 * 100 +
dprev * 10 + dig)
if (value % 8 != 0)
continue
ans += (i - 2)
ans -= (dp[i - 3][Sum[i]])
}
}
return ans
}
let Str = "6564525600"
let Len = Str.length
document.write(count(Str, Len))
</script>
|
Time Complexity: O(len), Where len is the length of string.
Auxiliary Space: O(MAX), Where MAX is the defined constant.
Please
Last Updated :
12 Jul, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...