Open In App

Count number of ways to generate digit K at the end.

Last Updated : 18 Oct, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] containing N elements, each element is between 0 to 9. The task is to count the number of ways modulo 109 + 7 these operations can be performed so that at the end array with digit K left. Following operations are allowed on the array and any of the operations can be performed more than one time.

  • Remove two leftmost elements x and y from the array and insert (x + y) % 10 at the left end of the array.
  • Remove two leftmost elements x and y from the array and insert (x * y) % 10 at the left end of the array.

Examples: 

Input: arr[] = {2, 7, 6}, K = 4
Output: 2
Explanation: Perform Operation 1 first and then Operation 2: The sequence becomes (2, 7, 6) ? (9, 6)? (4).
Perform Operation 2 first and then Operation 2 again: The sequence becomes (2, 7, 6) ? (4, 6)? (4).

Input: arr[] = {0 1 2 3 4}, K = 0
Output: 6

Naive approach: The problem can be solved by using the following idea:

Basic way to solve this problem is to generate all 2N combinations by recursive brute force.

Time Complexity: O(2N)
Auxiliary Space: O(1)

Efficient Approach:  The above approach can be optimized based on the following idea:

Dynamic programming can be used to solve this problem. It can be observed that there are N * 10 states but the recursive function is called exponential times. That means that some states are called repeatedly. So the idea is to store the value of states. 

Follow the steps below to solve the problem:

  • Create a recursive function that takes three parameters i representing i’th index, j representing the leftmost array element after the operation, and K representing the digit whose count at the end has to find out.
  • Check the base case if j is equal to K return 1 else return 0. 
  • Create a 2d array of dp[100001][10] with initially filled with -1.
  • If the answer for a particular state is computed then save it in dp[i][j].
  • If the answer for a particular state is already computed then just return dp[i][j].
  • Initialize a variable and to store the final result.
  • Perform operation 1 by making recursive call ans+= call( i+ 1, (j + arr[i + 1])).
  • Perform operation 2 by making recursive call ans+= call(i + 1, (j * arr[i + 1])).
  • Return the answer.

Below is the implementation of the above approach.

C++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
const int mod = 1e9 + 7;
 
// dp table initialized with - 1
int dp[100001][10];
 
// recursive function to count ways of performing
// following operations and finally ending up with K
int recur(int i, int j, int K, int arr[], int N)
{
    // Base case
    if (i == N - 1) {
 
        // return 1 if at end K is left
        if (j == K)
            return 1;
        else
            return 0;
    }
 
    // if answer for current state is already
    // calculated then just return dp[i][j]
    if (dp[i][j] != -1)
        return dp[i][j];
 
    // count of ways for creating K at end
    int ans = 0;
 
    // call recursive function for performing operation 1
    ans += recur(i + 1, (j + arr[i + 1]) % 10, K, arr, N)
           % mod;
 
    // call recursive function for performing operation 2
    ans += recur(i + 1, (j * arr[i + 1]) % 10, K, arr, N)
           % mod;
 
    // save and return dp value
    return dp[i][j] = ans;
}
 
// counting ways of performing following
// operations to end with K as last number.
void countWaysK(int arr[], int N, int K)
{
    // initializing dp with -1
    memset(dp, -1, sizeof(dp));
 
    cout << recur(0, arr[0], K, arr, N) << endl;
}
 
// Driver Code
int main()
{
    // Input 1
    int arr[] = { 2, 7, 6 };
    int N = sizeof(arr) / sizeof(arr[0]);
    int K = 4;
 
    // Function Call
    countWaysK(arr, N, K);
 
    // Input 2
    int arr1[] = { 0, 1, 2, 3, 4 };
    int N1 = sizeof(arr1) / sizeof(arr[0]);
    int K1 = 0;
 
    // Function call
    countWaysK(arr1, N1, K1);
    return 0;
}


Java




// Java code to implement the approach
 
import java.io.*;
import java.util.*;
 
class GFG {
    static final int mod = (int)(1e9 + 7);
    static int[][] dp;
 
    // recursive function to count ways of performing
    // following operations and finally ending up with K
    static int recur(int i, int j, int K, int[] arr, int N)
    {
        // Base case
        if (i == N - 1) {
            // return 1 if at end K is left
            if (j == K)
                return 1;
            else
                return 0;
        }
 
        // if answer for current state is already
        // calculated then just return dp[i][j]
        if (dp[i][j] != -1)
            return dp[i][j];
 
        // count of ways for creating K at end
        int ans = 0;
 
        // call recursive function for performing operation
        // 1
        ans += recur(i + 1, (j + arr[i + 1]) % 10, K, arr,
                     N)
               % mod;
 
        // call recursive function for performing operation
        // 2
        ans += recur(i + 1, (j * arr[i + 1]) % 10, K, arr,
                     N)
               % mod;
 
        // save and return dp value
        return dp[i][j] = ans;
    }
 
    // counting ways of performing following
    // operations to end with K as last number.
    static void countWaysK(int[] arr, int N, int K)
    {
        // initializing dp with -1
        dp = new int[100001][10];
        for (int[] row : dp) {
            Arrays.fill(row, -1);
        }
 
        System.out.println(recur(0, arr[0], K, arr, N));
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Input 1
        int[] arr = { 2, 7, 6 };
        int N = arr.length;
        int K = 4;
 
        // Function Call
        countWaysK(arr, N, K);
 
        // Input 2
        int[] arr1 = { 0, 1, 2, 3, 4 };
        int N1 = arr1.length;
        int K1 = 0;
 
        // Function call
        countWaysK(arr1, N1, K1);
    }
}
 
// This code is contributed by lokeshmvs21.


Python3




# Python code to implement the approach
mod=1e9+7
 
# dp table initialized with - 1
dp=[[-1 for i in range(10)] for j in range(100001)]
 
# recursive function to count ways of performing
# following operations and finally ending up with K
def recur(i, j, K, arr, N):
    # Base case
    if(i == N - 1):
        # return 1 if at end K is left
        if(j == K):
            return 1
        else:
            return 0
    # if answer for current state is already
    # calculated then just return dp[i][j]
    if(dp[i][j]!=-1):
        return dp[i][j]
     
    # count of ways for creating K at end
    ans=0
     
    # call recursive function for performing operation 1
    ans += recur(i + 1, (j + arr[i + 1]) % 10, K, arr, N)%mod
     
    # call recursive function for performing operation 2
    ans += recur(i + 1, (j * arr[i + 1]) % 10, K, arr, N)%mod
     
    # save and return dp value
    dp[i][j]=int(ans)
    return dp[i][j]
     
# counting ways of performing following
# operations to end with K as last number.
def countWaysK(arr, N, K):
    # initializing dp with -1
    for i in range(len(dp)):
        for j in range(len(dp[0])):
            dp[i][j]=-1
     
    print(recur(0, arr[0], K, arr, N))
     
# Driver Code
 
#Input 1
arr = [2,7,6]
N = len(arr)
K = 4
 
# Function Call
countWaysK(arr, N, K)
 
#Input 2
arr1 = [0,1,2,3,4]
N1 = len(arr1)
K1 = 0
 
# Function Call
countWaysK(arr1, N1, K1)
 
# This code is contributed by Pushpesh Raj.


C#




// C# code implementation for the above approach
using System;
using System.Linq;
 
public class GFG {
 
  static readonly int mod = (int)(1e9 + 7);
  static int[][] dp;
 
  // recursive function to count ways of performing
  // following operations and finally ending up with K
  static int recur(int i, int j, int K, int[] arr, int N)
  {
 
    // Base case
    if (i == N - 1)
    {
 
      // return 1 if at end K is left
      if (j == K)
        return 1;
      else
        return 0;
    }
 
    // if answer for current state is already
    // calculated then just return dp[i][j]
    if (dp[i][j] != -1)
      return dp[i][j];
 
    // count of ways for creating K at end
    int ans = 0;
 
    // call recursive function for performing operation
    // 1
    ans += recur(i + 1, (j + arr[i + 1]) % 10, K, arr,
                 N)
      % mod;
 
    // call recursive function for performing operation
    // 2
    ans += recur(i + 1, (j * arr[i + 1]) % 10, K, arr,
                 N)
      % mod;
 
    // save and return dp value
    return dp[i][j] = ans;
  }
 
  // counting ways of performing following
  // operations to end with K as last number.
  static void countWaysK(int[] arr, int N, int K)
  {
    // initializing dp with -1
    dp = Enumerable.Range(0, 100001)
      .Select(
      x
      => Enumerable.Range(0, 10).ToArray())
      .ToArray();
    for (int i = 0; i < dp.Length; i++) {
      for (int j = 0; j < dp[i].Length; j++) {
        dp[i][j] = -1;
      }
    }
 
    Console.WriteLine(recur(0, arr[0], K, arr, N));
  }
 
  static public void Main()
  {
 
    // Code
    // Input 1
    int[] arr = { 2, 7, 6 };
    int N = arr.Length;
    int K = 4;
 
    // Function Call
    countWaysK(arr, N, K);
 
    // Input 2
    int[] arr1 = { 0, 1, 2, 3, 4 };
    int N1 = arr1.Length;
    int K1 = 0;
 
    // Function call
    countWaysK(arr1, N1, K1);
  }
}
 
// This code is contributed by lokesh.


Javascript




// JavaScript code to implement the approach
 
let mod = 1e9 + 7;
 
// dp table initialized with - 1
let dp = new Array(100001);
for(let i = 0; i < 100001; i++){
    dp[i] = new Array(10).fill(-1);
}
 
// recursive function to count ways of performing
// following operations and finally ending up with K
function recur(i, j, K, arr, N)
{
    // Base case
    if (i == N - 1) {
 
        // return 1 if at end K is left
        if (j == K)
            return 1;
        else
            return 0;
    }
 
    // if answer for current state is already
    // calculated then just return dp[i][j]
    if (dp[i][j] != -1)
        return dp[i][j];
 
    // count of ways for creating K at end
    let ans = 0;
 
    // call recursive function for performing operation 1
    ans += recur(i + 1, (j + arr[i + 1]) % 10, K, arr, N)
           % mod;
 
    // call recursive function for performing operation 2
    ans += recur(i + 1, (j * arr[i + 1]) % 10, K, arr, N)
           % mod;
 
    // save and return dp value
    return dp[i][j] = ans;
}
 
// counting ways of performing following
// operations to end with K as last number.
function countWaysK(arr, N, K)
{
    console.log(recur(0, arr[0], K, arr, N))
}
 
// Driver Code
    // Input 1
    let arr = [2, 7, 6 ];
    let N = arr.length;
    let K = 4;
 
    // Function Call
    countWaysK(arr, N, K);
 
    // Input 2
    let arr1 = [0, 1, 2, 3, 4];
    let N1 = arr1.length;
    let K1 = 0;
 
    // Function call
    countWaysK(arr1, N1, K1);
    
   // This code is contributed by poojaagarwal2.


Output

2
6








Time Complexity: O(N)
Auxiliary Space: O(N)

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.

Implementation :

C++




#include <bits/stdc++.h>
using namespace std;
 
const int mod = 1e9 + 7;
 
// function to count ways of performing
// operations and ending up with K
void countWaysK(int arr[], int N, int K)
{
    // dp table to store the counts
    // initialize with all zeros
    int dp[N][10];
    memset(dp, 0, sizeof(dp));
 
    // initialize the first row of the table
    for (int j = 0; j < 10; j++) {
        if (j == arr[0]) {
            dp[0][j] = 1;
        }
    }
 
    // fill the remaining rows of the table
    for (int i = 1; i < N; i++) {
        for (int j = 0; j < 10; j++) {
            // for each cell, calculate the counts
            // by considering the two operations
            dp[i][(j + arr[i]) % 10]
                = (dp[i][(j + arr[i]) % 10] + dp[i - 1][j])
                  % mod;
            dp[i][(j * arr[i]) % 10]
                = (dp[i][(j * arr[i]) % 10] + dp[i - 1][j])
                  % mod;
        }
    }
 
    // the final answer is in dp[N-1][K]
    cout << dp[N - 1][K] << endl;
}
 
// Driver Code
int main()
{
    // Input 1
    int arr[] = { 2, 7, 6 };
    int N = sizeof(arr) / sizeof(arr[0]);
    int K = 4;
 
    // Function Call
    countWaysK(arr, N, K);
 
    // Input 2
    int arr1[] = { 0, 1, 2, 3, 4 };
    int N1 = sizeof(arr1) / sizeof(arr[0]);
    int K1 = 0;
 
    // Function call
    countWaysK(arr1, N1, K1);
    return 0;
}


Java




import java.util.Arrays;
 
public class Main {
    static final int mod = (int) 1e9 + 7;
 
      // function to count ways of performing
    // operations and ending up with K
    public static void countWaysK(int[] arr, int N, int K) {
       
          // dp table to store the counts
            // initialize with all zeros
        int[][] dp = new int[N][10];
       
          // initialize the first row of the table
        for (int[] row : dp) {
            Arrays.fill(row, 0);
        }
        for (int j = 0; j < 10; j++) {
            if (j == arr[0]) {
                dp[0][j] = 1;
            }
        }
       
          // fill the remaining rows of the table
        for (int i = 1; i < N; i++) {
            for (int j = 0; j < 10; j++) {
                  // for each cell, calculate the counts
                // by considering the two operations
                dp[i][(j + arr[i]) % 10] = (dp[i][(j + arr[i]) % 10] + dp[i - 1][j]) % mod;
                dp[i][(j * arr[i]) % 10] = (dp[i][(j * arr[i]) % 10] + dp[i - 1][j]) % mod;
            }
        }
          // the final answer is in dp[N-1][K]
        System.out.println(dp[N - 1][K]);
    }
 
      // Driver Code
    public static void main(String[] args) {
        int[] arr = {2, 7, 6};
        int N = arr.length;
        int K = 4;
        countWaysK(arr, N, K);
 
        int[] arr1 = {0, 1, 2, 3, 4};
        int N1 = arr1.length;
        int K1 = 0;
        countWaysK(arr1, N1, K1);
    }
}


Python3




mod = 10**9 + 7
 
# function to count ways of performing
# operations and ending up with K
def countWaysK(arr, N, K):
    # dp table to store the counts
    # initialize with all zeros
    dp = [[0] * 10 for _ in range(N)]
     
    # initialize the first row of the table   
    for j in range(10):
        if j == arr[0]:
            dp[0][j] = 1
     
    # fill the remaining rows of the table
    for i in range(1, N):
        for j in range(10):
          # for each cell, calculate the counts
          # by considering the two operations
            dp[i][(j + arr[i]) % 10] = (dp[i][(j + arr[i]) % 10] + dp[i - 1][j]) % mod
            dp[i][(j * arr[i]) % 10] = (dp[i][(j * arr[i]) % 10] + dp[i - 1][j]) % mod
     
    # the final answer is in dp[N-1][K]
    print(dp[N - 1][K])
# Driver code
arr = [2, 7, 6]
N = len(arr)
K = 4
 
countWaysK(arr, N, K)
 
arr1 = [0, 1, 2, 3, 4]
N1 = len(arr1)
K1 = 0
 
countWaysK(arr1, N1, K1)


C#




using System;
 
namespace CodeTranslationAssistant
{
    class Program
    {
        const int mod = 1000000007;
         
          // function to count ways of performing
        // operations and ending up with K
        static void CountWaysK(int[] arr, int N, int K)
        {
           
              // dp table to store the counts
            // initialize with all zeros
            int[,] dp = new int[N, 10];
           
           
              // initialize the first row of the table
            for (int i = 0; i < N; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    dp[i, j] = 0;
                }
            }
 
            for (int j = 0; j < 10; j++)
            {
                if (j == arr[0])
                {
                    dp[0, j] = 1;
                }
            }
 
              // fill the remaining rows of the table
            for (int i = 1; i < N; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                   
                      // for each cell, calculate the counts
                        // by considering the two operations
                    dp[i, (j + arr[i]) % 10] =
                      (dp[i, (j + arr[i]) % 10] + dp[i - 1, j]) % mod;
                    dp[i, (j * arr[i]) % 10] =
                      (dp[i, (j * arr[i]) % 10] + dp[i - 1, j]) % mod;
                }
            }
 
              // the final answer is in dp[N-1][K]
            Console.WriteLine(dp[N - 1, K]);
        }
 
       
          // Driver Code
        static void Main(string[] args)
        {
            int[] arr = { 2, 7, 6 };
            int N = arr.Length;
            int K = 4;
            CountWaysK(arr, N, K);
 
            int[] arr1 = { 0, 1, 2, 3, 4 };
            int N1 = arr1.Length;
            int K1 = 0;
            CountWaysK(arr1, N1, K1);
        }
    }
}


Javascript




const mod = 10**9 + 7;
 
// Function to count ways of performing
// operations and ending up with K
function countWaysK(arr, N, K) {
    // DP table to store the counts
    // Initialize with all zeros
    const dp = new Array(N);
    for (let i = 0; i < N; i++) {
        dp[i] = new Array(10).fill(0);
    }
 
    // Initialize the first row of the table
    for (let j = 0; j < 10; j++) {
        if (j === arr[0]) {
            dp[0][j] = 1;
        }
    }
 
    // Fill the remaining rows of the table
    for (let i = 1; i < N; i++) {
        for (let j = 0; j < 10; j++) {
            // For each cell, calculate the counts
            // by considering the two operations
            dp[i][(j + arr[i]) % 10] = (dp[i][(j + arr[i]) % 10] + dp[i - 1][j]) % mod;
            dp[i][(j * arr[i]) % 10] = (dp[i][(j * arr[i]) % 10] + dp[i - 1][j]) % mod;
        }
    }
 
    // The final answer is in dp[N-1][K]
    console.log(dp[N - 1][K]);
}
 
// Driver code
const arr = [2, 7, 6];
const N = arr.length;
const K = 4;
 
countWaysK(arr, N, K);
 
const arr1 = [0, 1, 2, 3, 4];
const N1 = arr1.length;
const K1 = 0;
 
countWaysK(arr1, N1, K1);
 
// This code is contributed by Dwaipayan Bandyopadhyay


Output

2
6








Time Complexity: O(N*10)
Auxiliary Space: O(N*10)

Related Articles:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads