Open In App

Count ways to create N digit number with given conditions

Last Updated : 17 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given the number N, the task for this problem is to find the number of ways of creating an N digit number whose bitwise XOR sum of all digits is non-zero and the difference between adjacent digits is greater than 1. (Print the answer modulo 109 + 7).

Examples:

Input: N = 1
Output: 9
Explanation: All single-digit numbers except 0 have bitwise XOR sum non-zero.

Input: N = 2
Output:  64
Explanation: All two-digit numbers satisfy this condition except 11, 22, 33, 44, 55, 66, 77, 88, 99, and all rest of the digits whose difference in adjacent digits is less than equal to 1.

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(6N)
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

  • dp[i][j][k] represents the number of ways of creating a number with size i digits, j last number picked and k is the bitwise XOR sum of all digits.
  • 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 the ith position of the number that has to be filled with a digit, j representing the previous digit picked, and k representing the bitwise XOR sum of all digits till the ith position.
  • Call the recursive function for choosing all digits from 0 to 9.
  • Base case if the number is formed with N digits and bitwise XOR sum is non zero then return 1 else return 0.
  • Create a 3d array of dp[N][10][16] 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[100001][11][16];
 
// Recursive Function to calculate count
// of ways forming a number of N digits
// whose xor sum of digits is non zero
// and difference between adjacent
// digits is greater than 1
int recur(int i, int j, int k)
{
 
    // Base case
    if (i == 0) {
        // if XOR sum is non zero
        if (k != 0)
 
            return 1;
        else
            return 0;
    }
 
    // If answer for current state is
    // already calculated then just return
    // dp[i][j + 1][k] + 1 is offset for
    // negative number storing as state
    if (dp[i][j + 1][k] != -1)
 
        return dp[i][j + 1][k];
 
    int ans = 0;
 
    for (int l = 0; l <= 9; l++) {
 
        // Skipping iteration when first
        // element becomes zero
        if (i == 0 and l == 0)
 
            continue;
 
        // Calling recursive function for
        // choosing l as digit for current
        // position if the difference of
        // last digit and l is greater
        // than 1
        if (abs(j - l) > 1)
            ans = (ans + recur(i - 1, l, k ^ l)) % MOD;
    }
 
    // Save and return dp value
    return dp[i][j][k] = ans;
}
 
// Function to calculate count of ways
// forming a number of N digits whose xor
// sum of digits is non zero and difference
// between adjacent digits is greater than 1
int countWaysTo(int N)
{
 
    // Initializing dp array with - 1
    memset(dp, -1, sizeof(dp));
 
    // N positions yet to fill, -1 denotes
    // first position is yet to be filled
    // and 0 is for current xor sum.
    return recur(N, -1, 0);
}
 
// Driver Code
int main()
{
    // Input 1
    int N = 1;
 
    // Function Call
    cout << countWaysTo(N) << endl;
 
    // Input 2
    int N1 = 2;
 
    // Function Call
    cout << countWaysTo(N1) << endl;
    return 0;
}


Java




// Java code to implement the approach
import java.io.*;
import java.util.*;
 
class GFG {
 
  static int MOD = (int)1e9 + 7;
 
  // DP table initialized with -1
  static int[][][] dp = new int[100001][11][16];
 
  // Recursive Function to calculate count of ways forming
  // a number of N digits whose xor sum of digits is non
  // zero and difference between adjacent digits is
  // greater than 1
  static int recur(int i, int j, int k)
  {
    // Base case
    if (i == 0) {
      // if XOR sum is non zero
      if (k != 0) {
        return 1;
      }
      else {
        return 0;
      }
    }
 
    // If answer for current state is already calculated
    // then just return dp[i][j + 1][k] + 1 is offset
    // for negative number storing as state
    if (dp[i][j + 1][k] != -1) {
      return dp[i][j + 1][k];
    }
    int ans = 0;
    for (int l = 0; l <= 9; l++) {
      // Skipping iteration when first element becomes
      // zero
      if (i == 0 && l == 0) {
        continue;
      }
 
      // Calling recursive function for choosing l as
      // digit for current position if the difference
      // of last digit and l is greater than 1
      if (Math.abs(j - l) > 1) {
        ans = (ans + recur(i - 1, l, k ^ l)) % MOD;
      }
    }
 
    // Save and return dp value
    dp[i][j + 1][k] = ans;
    return ans;
  }
 
  // Function to calculate count of ways forming a number
  // of N digits whose xor sum of digits is non zero and
  // difference between adjacent digits is greater than 1
  static int countWaysTo(int N)
  {
    // Initializing dp array with - 1
    for (int i = 0; i < dp.length; i++) {
      for (int j = 0; j < dp[i].length; j++) {
        Arrays.fill(dp[i][j], -1);
      }
    }
 
    // N positions yet to fill, -1 denotes first position
    // is yet to be filled and 0 is for current xor sum.
    return recur(N, -1, 0);
  }
 
  public static void main(String[] args)
  {
    // Input 1
    int N = 1;
 
    // Function Call
    System.out.println(countWaysTo(N));
 
    // Input 2
    int N1 = 2;
 
    // Function Call
    System.out.println(countWaysTo(N1));
  }
}
 
// This code is contributed by lokeshmvs21.


Python3




#Python code to implement the approach
 
MOD = 1e9 + 7
 
# DP table initialized with -1
dp = [[[-1 for col in range(100001)] for col in range(11)] for row in range(16)]
 
# Recursive Function to calculate count
# of ways forming a number of N digits
# whose xor sum of digits is non zero
# and difference between adjacent
# digits is greater than 1
def recur(i, j, k):
    # Base case
    if (i == 0):
        # if XOR sum is non zero
        if (k != 0):
            return 1
        else:
            return 0
 
    # If answer for current state is
    # already calculated then just return
    # dp[i][j + 1][k] + 1 is offset for
       # negative number storing as state
    if (dp[i][j + 1][k] != -1):
 
        return dp[i][j + 1][k]
 
    ans = 0
 
    for l in range(0, 10):
 
           # Skipping iteration when first
        # element becomes zero
        if (i == 0 and l == 0):
            continue
 
        # Calling recursive function for
        # choosing l as digit for current
        # position if the difference of
        # last digit and l is greater
        # than 1
        if (abs(j - l) > 1):
            ans = (ans + recur(i - 1, l, k ^ l)) % 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 whose xor
# sum of digits is non zero and difference
# between adjacent digits is greater than 1
def countWaysTo(N):
 
    #Initializing dp array with - 1
    # N positions yet to fill, -1 denotes
    # first position is yet to be filled
    # and 0 is for current xor sum.
    return recur(N, -1, 0)
 
# Driver Code
if __name__ == "__main__":
    # Input 1
    N = 1
 
    #Function Call
    print(int(countWaysTo(N)))
 
    #Input 2
    N1 = 2
 
    #Function Call
    print(int(countWaysTo(N1)))


C#




// C# code to implement the approach
 
using System;
 
public class GFG {
 
  static int MOD = (int)1e9 + 7;
  // DP table initialized with -1
  static int[, , ] dp = new int[100001, 11, 16];
 
  // Recursive Function to calculate count of ways forming
  // a number of N digits whose xor sum of digits is non
  // zero and difference between adjacent digits is
  // greater than 1
  static int Recur(int i, int j, int k)
  {
    // Base case
    if (i == 0) {
      // if XOR sum is non zero
      if (k != 0) {
        return 1;
      }
      else {
        return 0;
      }
    }
 
    // If answer for current state is already calculated
    // then just return dp[i][j + 1][k] + 1 is offset
    // for negative number storing as state
    if (dp[i, j + 1, k] != -1) {
      return dp[i, j + 1, k];
    }
 
    int ans = 0;
    for (int l = 0; l <= 9; l++) {
      // Skipping iteration when first element becomes
      // zero
      if (i == 0 && l == 0) {
        continue;
      }
 
      // Calling recursive function for choosing l as
      // digit for current position if the difference
      // of last digit and l is greater than 1
      if (Math.Abs(j - l) > 1) {
        ans = (ans + Recur(i - 1, l, k ^ l)) % MOD;
      }
    }
 
    // Save and return dp value
    dp[i, j + 1, k] = ans;
    return ans;
  }
 
  // Function to calculate count of ways forming a number
  // of N digits whose xor sum of digits is non zero and
  // difference between adjacent digits is greater than 1
  static int CountWaysTo(int N)
  {
    // Initializing dp array with - 1
    for (int i = 0; i < dp.GetLength(0); i++) {
      for (int j = 0; j < dp.GetLength(1); j++) {
        for (int k = 0; k < dp.GetLength(2); k++) {
          dp[i, j, k] = -1;
        }
      }
    }
 
    // N positions yet to fill, -1 denotes first position
    // is yet to be filled and 0 is for current xor sum.
    return Recur(N, -1, 0);
  }
 
  static public void Main()
  {
 
    // Code
 
    // Input 1
    int N = 1;
 
    // Function Call
    Console.WriteLine(CountWaysTo(N));
 
    // Input 2
    int N1 = 2;
 
    // Function Call
    Console.WriteLine(CountWaysTo(N1));
  }
}
 
// This code is contributed by karthik


Javascript




const MOD = 1e9 + 7;
 
let dp = new Array(100001).fill().map(() =>
new Array(11).fill().map(() => new Array(16).fill(-1)));
 
function recur(i, j, k) {
    // Base case
    if (i === 0) {
        // if XOR sum is non zero
        if (k !== 0) {
            return 1;
        } else {
            return 0;
        }
    }
 
    // If answer for current state is already calculated then just return
    if (dp[i][j+1][k] !== -1) {
        return dp[i][j+1][k];
    }
 
    let ans = 0;
 
    for (let l = 0; l <= 9; l++) {
        // Skipping iteration when first element becomes zero
        if (i === 0 && l === 0) {
            continue;
        }
 
        // Calling recursive function for choosing l
        // as digit for current position if the difference
        // of last digit and l is greater than 1
        if (Math.abs(j - l) > 1) {
            ans = (ans + recur(i - 1, l, k ^ l)) % MOD;
        }
    }
 
    // Save and return dp value
    dp[i][j+1][k] = ans;
    return ans;
}
 
 
 
// Function to calculate count of ways
// forming a number of N digits whose xor
// sum of digits is non zero and difference
// between adjacent digits is greater than 1
function countWaysTo(N) {
    // N positions yet to fill, -1 denotes
    // first position is yet to be filled
    // and 0 is for current xor sum.
    return recur(N, -1, 0);
}
 
// Driver Code
 
// Input 1
let N = 1;
 
// Function Call
console.log(countWaysTo(N));
 
// Input 2
let N1 = 2;
 
// Function Call
console.log(countWaysTo(N1));


Output

9
64

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

Related Articles:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads