Open In App

Number of substrings divisible by 8 but not by 3

Improve
Improve
Like Article
Like
Save
Share
Report

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++




// CPP Program to count substrings which are
// divisible by 8 but not by 3
#include <bits/stdc++.h>
using namespace std;
#define MAX 1000
 
// Returns count of substrings divisible by 8
// but not by 3.
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;
 
    // Iterating the string.
    for (int i = 1; i <= len; i++)
    {
        dig = int(s[i-1])-48;
        cur += dig;
        cur %= 3;
 
        sum[i] = cur;
 
        // Prefix sum of number of substrings whose
        // sum of digits modulo 3 is 0, 1, 2.
        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;
 
    // Iterating the string.
    for (int i = 1; i <= len; i++)
    {
        dig = int(s[i-1])-48;
 
        // Since single digit 8 is divisible
        // by 8 and not by 3.
        if (dig == 8)
            ans++;
 
        // Taking two digit number.
        if (i-2 >= 0)
        {
            dprev = int(s[i-2])-48; // 10th position
            value = dprev*10 + dig; // Complete 2 digit
                                    // number
 
            if ((value%8 == 0) && (value%3 != 0))
                ans++;
        }
 
        // Taking 3 digit number.
        if (i-3 >= 0)
        {
            dprev2 = int(s[i-3])-48; // 100th position
            dprev = int(s[i-2])-48; // 10th position
 
            // Complete 3 digit number.
            value = dprev2*100 + dprev*10 + dig;
 
            if (value%8 != 0)
                continue;
 
            // If number formed is divisible by 8 then
            // last 3 digits are also divisible by 8.
            // Then all the substring ending at this
            // index is divisible.
            ans += (i-2);
 
            // But those substring also contain number
            // which are not divisible by 3 so
            // remove them.
            ans -= (dp[i-3][sum[i]]);
        }
    }
 
    return ans;
}
 
// Driven Program
int main()
{
    char str[] = "6564525600";
    int len = strlen(str);
    cout << count(str, len) <<endl;
    return 0;
}


Java




// Java program to count substrings which are
// divisible by 8 but not by 3
import java.io.*;
 
class GFG
{
    // Function that returns count of substrings divisible by 8
    // but not by 3
    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;
  
        // Iterating the string.
        for (int i = 1; i <= len; i++)
        {
            dig = (int)(s.charAt(i-1)) - 48;
            cur += dig;
            cur %= 3;
  
            sum[i] = cur;
  
            // Prefix sum of number of substrings whose
            // sum of digits modulo 3 is 0, 1, 2.
            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;
  
        // Iterating the string.
        for (int i = 1; i <= len; i++)
        {
            dig = (int)(s.charAt(i-1)) - 48;
  
            // Since single digit 8 is divisible
            // by 8 and not by 3.
            if (dig == 8)
                ans++;
  
            // Taking two digit number.
            if (i-2 >= 0)
            {
                dprev = (int)(s.charAt(i-2)) - 48// 10th position
                value = dprev*10 + dig;  // Complete 2 digit
                                     // number
     
                if ((value%8 == 0) && (value%3 != 0))
                    ans++;
            }
  
            // Taking 3 digit number.
            if (i-3 >= 0)
            {
                dprev2 = (int)(s.charAt(i-3)) - 48; // 100th position
                dprev  = (int)(s.charAt(i-2)) - 48// 10th position
  
                // Complete 3 digit number.
                value = dprev2*100 + dprev*10 + dig;
  
                if (value%8 != 0)
                    continue;
  
                // If number formed is divisible by 8 then
                // last 3 digits are  also divisible by 8.
                // Then all the substring ending at this
                // index is divisible.
                ans += (i-2);
  
                // But those substring also contain number
                // which are not divisible by 3 so
                // remove them.
                ans -= (dp[i-3][sum[i]]);
            }
        }
  
        return ans;
    }
     
    // driver program
    public static void main (String[] args)
    {
        String str = "6564525600";
        int len = str.length();
        System.out.println(count(str, len));
    }
}
 
// Contributed by Pramod Kumar


Python3




# Python3 Program to count substrings
# which are divisible by 8 but not by 3
 
# Returns count of substrings
# divisible by 8 but not by 3.
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
 
    # Iterating the string.
    for i in range(1, Len + 1):
        dig = int(s[i - 1]) - 48
        cur += dig
        cur %= 3
 
        Sum[i] = cur
 
        # Prefix sum of number of substrings
        # whose sum of digits modulo 3 is
        # 0, 1, 2.
        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
 
    # Iterating the string.
    for i in range(1, Len + 1):
        dig = int(s[i - 1]) - 48
 
        # Since single digit 8 is
        # divisible by 8 and not by 3.
        if dig == 8:
            ans += 1
 
        # Taking two digit number.
        if i - 2 >= 0:
            dprev = int(s[i - 2]) - 48 # 10th position
            value = dprev * 10 + dig   # Complete 2 digit
                                       # number
 
            if (value % 8 == 0) and (value % 3 != 0):
                ans += 1
 
        # Taking 3 digit number.
        if i - 3 >= 0:
            dprev2 = int(s[i - 3]) - 48 # 100th position
            dprev = int(s[i - 2]) - 48 # 10th position
 
            # Complete 3 digit number.
            value = (dprev2 * 100 +
                     dprev * 10 + dig)
 
            if value % 8 != 0:
                continue
 
            # If number formed is divisible by 8
            # then last 3 digits are also divisible
            # by 8. Then all the substring ending
            # at this index are divisible.
            ans += (i - 2)
 
            # But those substring also contain
            # number which are not divisible
            # by 3 so remove them.
            ans -= (dp[i - 3][Sum[i]])
 
    return ans
 
# Driver Code
MAX = 1000
Str = "6564525600"
Len = len(Str)
print(count(Str, Len))
 
# This code is contributed
# by PranchalK


C#




// C# program to count substrings which are
// divisible by 8 but not by 3
using System;
 
class GFG
{
    // Function that returns count of substrings
    // divisible by 8 but not by 3
    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;
 
        // Iterating the string.
        for (int i = 1; i <= len; i++)
        {
            dig = (int)(s[i-1]) - 48;
            cur += dig;
            cur %= 3;
 
            sum[i] = cur;
 
            // Prefix sum of number of substrings whose
            // sum of digits modulo 3 is 0, 1, 2.
            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;
 
        // Iterating the string.
        for (int i = 1; i <= len; i++)
        {
            dig = (int)(s[i-1]) - 48;
 
            // Since single digit 8 is divisible
            // by 8 and not by 3.
            if (dig == 8)
                ans++;
 
            // Taking two digit number.
            if (i-2 >= 0)
            {
                dprev = (int)(s[i-2]) - 48; // 10th position
                value = dprev*10 + dig;     // Complete 2 digit number
     
                if ((value % 8 == 0) && (value % 3 != 0))
                    ans++;
            }
 
            // Taking 3 digit number.
            if (i - 3 >= 0)
            {
                dprev2 = (int)(s[i-3]) - 48; // 100th position
                dprev = (int)(s[i-2]) - 48; // 10th position
 
                // Complete 3 digit number.
                value = dprev2 * 100 + dprev * 10 + dig;
 
                if (value % 8 != 0)
                    continue;
 
                // If number formed is divisible by 8 then
                // last 3 digits are also divisible by 8.
                // Then all the substring ending at this
                // index is divisible.
                ans += (i - 2);
 
                // But those substring also contain number
                // which are not divisible by 3 so
                // remove them.
                ans -= (dp[i - 3,sum[i]]);
            }
        }
 
        return ans;
    }
     
    // driver program
    public static void Main (String[] args)
    {
        String str = "6564525600";
        int len = str.Length;
        Console.Write(count(str, len));
    }
}
 
// This code is contributed by parashar.


Javascript




<script>
 
// JavaScript Program to count substrings
// which are divisible by 8 but not by 3
 
// Returns count of substrings
// divisible by 8 but not by 3.
 
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
 
    // Iterating the string.
    for(let i=1;i<Len + 1;i++){
        dig = s.charCodeAt(i - 1) - '0'.charCodeAt(0)
        cur += dig
        cur %= 3
 
        Sum[i] = cur
 
        // Prefix sum of number of substrings
        // whose sum of digits modulo 3 is
        // 0, 1, 2.
        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
 
    // Iterating the string.
    for(let i=1;i<Len + 1;i++){
        dig = s.charCodeAt(i - 1) - '0'.charCodeAt(0)
 
        // Since single digit 8 is
        // divisible by 8 and not by 3.
        if(dig == 8)
            ans += 1
 
        // Taking two digit number.
        if(i - 2 >= 0){
            dprev = s.charCodeAt(i - 2) - '0'.charCodeAt(0) // 10th position
            value = dprev * 10 + dig // Complete 2 digit
                                    // number
 
            if ((value % 8 == 0) && (value % 3 != 0))
                ans += 1
        }
 
        // Taking 3 digit number.
        if(i - 3 >= 0){
            dprev2 = s.charCodeAt(i - 3) - '0'.charCodeAt(0) // 100th position
            dprev = s.charCodeAt(i - 2) - '0'.charCodeAt(0) // 10th position
 
            // Complete 3 digit number.
            value = (dprev2 * 100 +
                    dprev * 10 + dig)
 
            if(value % 8 != 0)
                continue
 
            // If number formed is divisible by 8
            // then last 3 digits are also divisible
            // by 8. Then all the substring ending
            // at this index are divisible.
            ans += (i - 2)
 
            // But those substring also contain
            // number which are not divisible
            // by 3 so remove them.
            ans -= (dp[i - 3][Sum[i]])
        }
    }
 
    return ans
}
 
// Driver Code
let Str = "6564525600"
let Len = Str.length
document.write(count(Str, Len))
 
// This code is contributed by shinjanpatra
 
</script>


Output

15

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
Previous
Next
Share your thoughts in the comments
Similar Reads