Number of substrings divisible by 8 but not by 3

Given a string of digits “0-9”. The task is 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 substring ending at this index must be divisible by 8 i.e (i-3) substrings. But it will also contain those substring which are divisible by 3, so simply remove them using dp[i][j].

C/C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 mudolo 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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 mudolo 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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 mudolo 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.

chevron_right


Output:

15

This article is contributed by Anuj Chauhan. 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 write comments if you find anything incorrect, or you want to share more information about the topic discussed above.



My Personal Notes arrow_drop_up

Improved By : parashar