Count ways to create N digit number with given conditions
Last Updated :
17 Feb, 2023
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++
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
int dp[100001][11][16];
int recur( int i, int j, int k)
{
if (i == 0) {
if (k != 0)
return 1;
else
return 0;
}
if (dp[i][j + 1][k] != -1)
return dp[i][j + 1][k];
int ans = 0;
for ( int l = 0; l <= 9; l++) {
if (i == 0 and l == 0)
continue ;
if ( abs (j - l) > 1)
ans = (ans + recur(i - 1, l, k ^ l)) % MOD;
}
return dp[i][j][k] = ans;
}
int countWaysTo( int N)
{
memset (dp, -1, sizeof (dp));
return recur(N, -1, 0);
}
int main()
{
int N = 1;
cout << countWaysTo(N) << endl;
int N1 = 2;
cout << countWaysTo(N1) << endl;
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static int MOD = ( int )1e9 + 7 ;
static int [][][] dp = new int [ 100001 ][ 11 ][ 16 ];
static int recur( int i, int j, int k)
{
if (i == 0 ) {
if (k != 0 ) {
return 1 ;
}
else {
return 0 ;
}
}
if (dp[i][j + 1 ][k] != - 1 ) {
return dp[i][j + 1 ][k];
}
int ans = 0 ;
for ( int l = 0 ; l <= 9 ; l++) {
if (i == 0 && l == 0 ) {
continue ;
}
if (Math.abs(j - l) > 1 ) {
ans = (ans + recur(i - 1 , l, k ^ l)) % MOD;
}
}
dp[i][j + 1 ][k] = ans;
return ans;
}
static int countWaysTo( int N)
{
for ( int i = 0 ; i < dp.length; i++) {
for ( int j = 0 ; j < dp[i].length; j++) {
Arrays.fill(dp[i][j], - 1 );
}
}
return recur(N, - 1 , 0 );
}
public static void main(String[] args)
{
int N = 1 ;
System.out.println(countWaysTo(N));
int N1 = 2 ;
System.out.println(countWaysTo(N1));
}
}
|
Python3
MOD = 1e9 + 7
dp = [[[ - 1 for col in range ( 100001 )] for col in range ( 11 )] for row in range ( 16 )]
def recur(i, j, k):
if (i = = 0 ):
if (k ! = 0 ):
return 1
else :
return 0
if (dp[i][j + 1 ][k] ! = - 1 ):
return dp[i][j + 1 ][k]
ans = 0
for l in range ( 0 , 10 ):
if (i = = 0 and l = = 0 ):
continue
if ( abs (j - l) > 1 ):
ans = (ans + recur(i - 1 , l, k ^ l)) % MOD
dp[i][j][k] = ans
return dp[i][j][k]
def countWaysTo(N):
return recur(N, - 1 , 0 )
if __name__ = = "__main__" :
N = 1
print ( int (countWaysTo(N)))
N1 = 2
print ( int (countWaysTo(N1)))
|
C#
using System;
public class GFG {
static int MOD = ( int )1e9 + 7;
static int [, , ] dp = new int [100001, 11, 16];
static int Recur( int i, int j, int k)
{
if (i == 0) {
if (k != 0) {
return 1;
}
else {
return 0;
}
}
if (dp[i, j + 1, k] != -1) {
return dp[i, j + 1, k];
}
int ans = 0;
for ( int l = 0; l <= 9; l++) {
if (i == 0 && l == 0) {
continue ;
}
if (Math.Abs(j - l) > 1) {
ans = (ans + Recur(i - 1, l, k ^ l)) % MOD;
}
}
dp[i, j + 1, k] = ans;
return ans;
}
static int CountWaysTo( int N)
{
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;
}
}
}
return Recur(N, -1, 0);
}
static public void Main()
{
int N = 1;
Console.WriteLine(CountWaysTo(N));
int N1 = 2;
Console.WriteLine(CountWaysTo(N1));
}
}
|
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) {
if (i === 0) {
if (k !== 0) {
return 1;
} else {
return 0;
}
}
if (dp[i][j+1][k] !== -1) {
return dp[i][j+1][k];
}
let ans = 0;
for (let l = 0; l <= 9; l++) {
if (i === 0 && l === 0) {
continue ;
}
if (Math.abs(j - l) > 1) {
ans = (ans + recur(i - 1, l, k ^ l)) % MOD;
}
}
dp[i][j+1][k] = ans;
return ans;
}
function countWaysTo(N) {
return recur(N, -1, 0);
}
let N = 1;
console.log(countWaysTo(N));
let N1 = 2;
console.log(countWaysTo(N1));
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Related Articles:
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...