Open In App

Count of ways to form N digit number div by 3 with no adjacent duplicates

Improve
Improve
Like Article
Like
Save
Share
Report

Given integer N, the task is to count the number of ways( modulo 109 + 7) to create an N digit number from digits 1 to 9 such that adjacent digits are different and the number is divisible by 3.

Examples: 

Input: N = 1
Output: 3
Explanation: 3, 6, and 9 are the only possible numbers.

Input: N = 2
Output:  24
Explanation: 12, 15, 18, 21, 24, 27, 36, 39, 42, 45, 48, 51, 54, 57, 63, 69, 72, 75, 78, 81, 84, 87, 93,  and 96 are possible numbers. 

Naive approach: The basic way to solve the problem is as follows:

The basic way to solve this problem is to generate all possible combinations by using a recursive approach.

Time Complexity: O(8N)
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

  • By divisibility test of 3: it’s enough to keep track of the (sum of digits % 3) if its zero then number is divisible by 3.
  • dp[i][j][k] represents the number of ways of creating number with size i digits,   j last number picked and k is sum of digits picked modulo 3. 

It can be observed that the recursive function is called exponential times. That means that some states are called repeatedly. So the idea is to store the value of each state. This can be done using by the store the value of a state and whenever the function is called, returning the stored value without computing again.

Follow the steps below to solve the problem:

  • Create a recursive function that takes three parameters i representing i’th position of number that has to be filled with a digit, j representing the previous digit picked, and k representing the sum of digits modulo 3. 
  • Call the recursive function for choosing all digits from 1 to 9.
  • Base case if the number is formed with N digits and j is zero then return 1 else return 0.
  • Create a 3d array of dp[N][11][3] initially filled with -1.
  • If the answer for a particular state is computed then save it in dp[i][j][k].
  • If the answer for a particular state is already computed then just return dp[i][j][k].

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[1000001][11][3];
 
// Recursive Function to calculate count of
// ways forming a number of N digits which is
// divisible by 3 and adjacent digits are
// not same.
int recur(int i, int j, int k)
{
 
    // base case
    if (i == 0) {
 
        // if divisible by 3
        if (k % 3 == 0)
            return 1;
 
        // Otherwise
        else
            return 0;
    }
 
    // If answer for current state is already
    // calculated then just return dp[i][j]
    if (dp[i][j][k] != -1)
 
        return dp[i][j][k];
 
    int ans = 0;
 
    for (int l = 1; l <= 9; l++) {
 
        // Skipping iteration when adjacent
        // element becomes equal (j == l) where
        // j is last number and l is number
        // of current iteration
        if (j == l)
            continue;
 
        // Calling recursive function for
        // choosing l as digit for
        // current position
        ans = (ans + recur(i - 1, l, (k + l) % 3)) % MOD;
    }
 
    // Save and return dp value
    return dp[i][j][k] = ans;
}
 
// Function to calculate count of ways
// forming a number of N digits which is
// divisible by 3 and adjacent digits are
// not same.
int countWays(int N)
{
 
    // Initializing dp array with - 1
    memset(dp, -1, sizeof(dp));
 
    return recur(N, -1, 0);
}
 
// Driver Code
int main()
{
    // Input 1
    int N = 1;
 
    // Function Call
    cout << countWays(N) << endl;
 
    // Input 2
    int N1 = 2;
 
    // Function Call
    cout << countWays(N1) << endl;
    return 0;
}


C#




// C# implementation of the above approach
using System;
using System.Collections.Generic;
using System.Linq;
 
class GFG {
 
  const int MOD = 1000000007;
 
  // DP table initialized with -1
  static int[,,] dp=new int[10001,11,3];
 
  // Recursive Function to calculate count of
  // ways forming a number of N digits which is
  // divisible by 3 and adjacent digits are
  // not same.
  static int recur(int i, int j, int k)
  {
 
    // base case
    if (i == 0) {
 
      // if divisible by 3
      if (k % 3 == 0)
        return 1;
 
      // Otherwise
      else
        return 0;
    }
 
    // If answer for current state is already
    // calculated then just return dp[i][j]
    if (dp[i,j,k] != -1)
 
      return dp[i,j,k];
 
    int ans = 0;
 
    for (int l = 1; l <= 9; l++) {
 
      // Skipping iteration when adjacent
      // element becomes equal (j == l) where
      // j is last number and l is number
      // of current iteration
      if (j == l)
        continue;
 
      // Calling recursive function for
      // choosing l as digit for
      // current position
      ans = (ans + recur(i - 1, l, (k + l) % 3)) % MOD;
    }
 
    // Save and return dp value
    return dp[i,j,k] = ans;
  }
 
  // Function to calculate count of ways
  // forming a number of N digits which is
  // divisible by 3 and adjacent digits are
  // not same.
  static int countWays(int N)
  {
 
    // Initializing dp array with - 1
    for(int i=0; i<10001; i++)
    {
      for(int j=0; j<11; j++)
      {
        for(int k=0; k<3; k++)
          dp[i,j,k]=-1;
      }
    }
    return recur(N, 0, 0);
  }
 
  // Driver Code   
  public static void Main()
  {
    // Input 1
    int N = 1;
 
    // Function Call
    Console.WriteLine(countWays(N));
 
    // Input 2
    int N1 = 2;
 
    // Function Call
    Console.WriteLine(countWays(N1));
  }
}
 
// This code is contributed by agrawalpoojaa976.


Javascript




const MOD = 1e9 + 7;
 
// DP table initialized with -1
let dp = new Array(10001).fill(0).map(() =>
new Array(11).fill(0).map(() => new Array(3).fill(-1)));
 
// Recursive Function to calculate count of
// ways forming a number of N digits which is
// divisible by 3 and adjacent digits are
// not same.
function recur(i, j, k) {
 
    // base case
    if (i === 0) {
 
        // if divisible by 3
        if (k % 3 === 0)
            return 1;
 
        // Otherwise
        else
            return 0;
    }
 
    // If answer for current state is already
    // calculated then just return dp[i][j]
    if (dp[i][j][k] !=-1)
 
        return dp[i][j][k];
 
    let ans = 0;
 
    for (let l = 1; l <= 9; l++) {
 
        // Skipping iteration when adjacent
        // element becomes equal (j == l) where
        // j is last number and l is number
        // of current iteration
        if (j === l)
            continue;
 
        // Calling recursive function for
        // choosing l as digit for
        // current position
        ans = (ans + recur(i - 1, l, (k + l) % 3)) % MOD;
    }
 
    // Save and return dp value
    dp[i][j][k] = ans;
    return dp[i][j][k];
}
 
// Function to calculate count of ways
// forming a number of N digits which is
// divisible by 3 and adjacent digits are
// not same.
function countWays(N) {
    return recur(N, 0, 0);
}
 
// Driver Code
 
// Input 1
let N = 1;
 
// Function Call
console.log(countWays(N));
 
// Input 2
let N1 = 2;
 
// Function Call
console.log(countWays(N1));


Java




import java.util.Arrays;
 
class GFG {
    static int MOD = 1000000007;
    static int[][][] dp = new int[10001][11][3];
    static int recur(int i, int j, int k) {
        if (i == 0) {
            if (k % 3 == 0) {
                return 1;
            } else {
                return 0;
            }
        }
        if (dp[i][j][k] != -1) {
            return dp[i][j][k];
        }
        int ans = 0;
        for (int l = 1; l <= 9; l++) {
            if (j == l) {
                continue;
            }
            ans = (ans + recur(i - 1, l, (k + l) % 3)) % MOD;
        }
        return dp[i][j][k] = ans;
    }
    static int countWays(int N) {
        for (int i = 0; i < 10001; i++) {
            for (int j = 0; j < 11; j++) {
                Arrays.fill(dp[i][j], -1);
            }
        }
        return recur(N, 0, 0);
    }
    public static void main(String[] args) {
        int N = 1;
        System.out.println(countWays(N));
        int N1 = 2;
        System.out.println(countWays(N1));
    }
}


Python3




MOD = 1000000007
dp = [[[-1 for _ in range(3)] for _ in range(11)] for _ in range(10001)]
 
def recur(i, j, k):
    if i == 0:
        if k % 3 == 0:
            return 1
        else:
            return 0
    if dp[i][j][k] != -1:
        return dp[i][j][k]
    ans = 0
    for l in range(1, 10):
        if j == l:
            continue
        ans = (ans + recur(i - 1, l, (k + l) % 3)) % MOD
    dp[i][j][k] = ans
    return ans
 
def countWays(N):
    return recur(N, 0, 0)
 
print(countWays(1))
print(countWays(2))


Output

3
24

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

Related Articles:



Last Updated : 12 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads