Count ways to generate N-length array with 0s, 1s, and 2s such that sum of all adjacent pairwise products is K
Last Updated :
04 Oct, 2023
Given two integers N and K, the task is to find the number of N-length arrays that can be generated by using the values 0, 1, and 2 any number of times, such that the sum of all adjacent pairwise products of the array is K.
Examples:
Input: N = 4, K = 3
Output: 5
Explanation: All possible arrangements are:
- arr[] = {2, 1, 1, 0}, Adjacent pairwise product sum = 2 * 1 + 1 * 1 + 1 * 0 = 3.
- arr[] = {0, 2, 1, 1}, Adjacent pairwise product sum = 0 * 2 + 2 * 1 + 1 * 1 = 3.
- arr[] = {1, 1, 2, 0}, Adjacent pairwise product sum = 1 * 1 + 1 * 2 + 2 * 0 = 3.
- arr[] = {0, 1, 1, 2}, Adjacent pairwise product sum is 0 * 1 + 1 * 1 + 1 * 2 = 3.
- arr[] = {1, 1, 1, 1}, Adjacent pairwise product sum = 1*1 + 1*1 + 1*1 = 3.
Input: N = 10, K = 9
Output: 3445
Naive Approach: The simplest approach is to generate all possible arrangements of the array whose value can be 0, 1, or 2 and count those arrays whose adjacent pairwise product sum is K. Print the count of such arrangements.
Time Complexity: O(N*3N )
Auxiliary Space: O(N)
Efficient Approach: To optimize the above approach, the optimal idea is to use Dynamic Programming. The overlapping subproblems can be stored in a dp[][][] table where dp[i][remaining][previous] stores the answer for up to position (N – 1) from position ‘i’ with ‘remaining’ as the remaining value to be added and ‘previous’ as the number placed in the position (i – 1). There can be three cases possible for any position ‘i’:
- Assign ‘0’ to position ‘i’.
- Assign ‘1’ to position ‘i’.
- Assign ‘2’ to position ‘i’.
Follow the steps below to solve the problem:
- Initialize the dp[][][] to store the current position, remaining value to be added, and element at the previous position.
- The transition state is as follows :
dp[i][remaining_sum][previous_element] = dp(assign 0 to pos ‘i’) + dp(assign 1 to ‘i’ ) + dp(assign 2 to ‘i’)
- Solve the above recurrence relation recursively and store the result for each state in the dp table. For overlapping, subproblems use the stored result in the dp table.
- After the above recursive calls end, print the total number of arrays having adjacent pairwise products of the array is K return by the function.
Below is an implementation of the above approach :
C++
#include <bits/stdc++.h>
using namespace std;
int waysForPairwiseSumToBeK(
int i, int rem, int previous,
int N, int dp[][15][3])
{
if (i == N) {
if (rem == 0)
return 1;
else
return 0;
}
if (rem < 0)
return 0;
if (dp[i][rem][previous] != -1)
return dp[i][rem][previous];
int ways = 0;
ways += waysForPairwiseSumToBeK(
i + 1, rem, 0, N, dp);
ways += waysForPairwiseSumToBeK(
i + 1, rem - (previous), 1, N, dp);
ways += waysForPairwiseSumToBeK(
i + 1, rem - (2 * previous), 2, N, dp);
return dp[i][rem][previous] = ways;
}
void countOfArrays( int i, int rem,
int previous, int N)
{
int dp[15][15][3];
memset (dp, -1, sizeof dp);
int totWays
= waysForPairwiseSumToBeK(
i, rem, previous, N, dp);
cout << totWays << ' ' ;
}
int main()
{
int N = 4, K = 3;
countOfArrays(0, K, 0, N);
return 0;
}
|
Java
import java.util.*;
class solution{
static int waysForPairwiseSumToBeK( int i, int rem,
int previous,
int N, int [][][]dp)
{
if (i == N)
{
if (rem == 0 )
return 1 ;
else
return 0 ;
}
if (rem < 0 )
return 0 ;
if (dp[i][rem][previous] != - 1 )
return dp[i][rem][previous];
int ways = 0 ;
ways += waysForPairwiseSumToBeK(i + 1 , rem,
0 , N, dp);
ways += waysForPairwiseSumToBeK(i + 1 , rem -
(previous),
1 , N, dp);
ways += waysForPairwiseSumToBeK(i + 1 , rem -
( 2 * previous),
2 , N, dp);
dp[i][rem][previous] = ways;
return ways;
}
static void countOfArrays( int i, int rem,
int previous, int N)
{
int [][][]dp = new int [ 15 ][ 15 ][ 3 ];
for ( int p = 0 ; p < 15 ; p++)
{
for ( int q = 0 ; q < 15 ; q++)
{
for ( int r = 0 ; r < 3 ; r++)
dp[p][q][r] = - 1 ;
}
}
int totWays = waysForPairwiseSumToBeK(i, rem,
previous,
N, dp);
System.out.print(totWays);
}
public static void main(String args[])
{
int N = 4 , K = 3 ;
countOfArrays( 0 , K, 0 , N);
}
}
|
Python3
def waysForPairwiseSumToBeK(i, rem, previous, N, dp):
if (i = = N):
if (rem = = 0 ):
return 1
else :
return 0
if (rem < 0 ):
return 0
if (dp[i][rem][previous] ! = - 1 ):
return dp[i][rem][previous]
ways = 0
ways + = waysForPairwiseSumToBeK(i + 1 , rem,
0 , N, dp)
ways + = waysForPairwiseSumToBeK(i + 1 ,
rem - (previous),
1 , N, dp)
ways + = waysForPairwiseSumToBeK(i + 1 ,
rem - ( 2 * previous),
2 , N, dp)
dp[i][rem][previous] = ways
return ways
def countOfArrays(i, rem, previous, N):
dp = [[[ - 1 for i in range ( 3 )]
for j in range ( 15 )]
for k in range ( 15 )]
totWays = waysForPairwiseSumToBeK(i, rem,
previous,
N, dp)
print (totWays, end = " " )
if __name__ = = '__main__' :
N = 4
K = 3
countOfArrays( 0 , K, 0 , N)
|
C#
using System;
class GFG{
static int waysForPairwiseSumToBeK( int i, int rem,
int previous,
int N, int [,,]dp)
{
if (i == N)
{
if (rem == 0)
return 1;
else
return 0;
}
if (rem < 0)
return 0;
if (dp[i, rem, previous] != -1)
return dp[i, rem, previous];
int ways = 0;
ways += waysForPairwiseSumToBeK(i + 1, rem,
0, N, dp);
ways += waysForPairwiseSumToBeK(i + 1, rem -
(previous),
1, N, dp);
ways += waysForPairwiseSumToBeK(i + 1, rem -
(2 * previous),
2, N, dp);
dp[i, rem, previous] = ways;
return ways;
}
static void countOfArrays( int i, int rem,
int previous, int N)
{
int [,,]dp = new int [ 15, 15, 3 ];
for ( int p = 0; p < 15; p++)
{
for ( int q = 0; q < 15; q++)
{
for ( int r = 0; r < 3; r++)
dp[p, q, r] = -1;
}
}
int totWays = waysForPairwiseSumToBeK(i, rem,
previous,
N, dp);
Console.Write(totWays);
}
public static void Main(String []args)
{
int N = 4, K = 3;
countOfArrays(0, K, 0, N);
}
}
|
Javascript
<script>
function waysForPairwiseSumToBeK(i,rem,previous,N,dp)
{
if (i == N)
{
if (rem == 0)
return 1;
else
return 0;
}
if (rem < 0)
return 0;
if (dp[i][rem][previous] != -1)
return dp[i][rem][previous];
let ways = 0;
ways += waysForPairwiseSumToBeK(i + 1, rem,
0, N, dp);
ways += waysForPairwiseSumToBeK(i + 1, rem -
(previous),
1, N, dp);
ways += waysForPairwiseSumToBeK(i + 1, rem -
(2 * previous),
2, N, dp);
dp[i][rem][previous] = ways;
return ways;
}
function countOfArrays(i,rem,previous,N)
{
let dp = new Array(15);
for (let i = 0; i < 15; i++)
{
dp[i] = new Array(15);
for (let j = 0; j < 15; j++)
{
dp[i][j] = new Array(3);
for (let k = 0; k < 3; k++)
dp[i][j][k] = -1;
}
}
let totWays = waysForPairwiseSumToBeK(i, rem,
previous,
N, dp);
document.write(totWays);
}
let N = 4, K = 3;
countOfArrays(0, K, 0, N);
</script>
|
Time Complexity: O(N*K)
Auxiliary Space: O(N*K)
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.
Steps to solve this problem :
- Create a table to store the solution of the subproblems.
- Initialize the table with base cases
- Fill up the table iteratively
- Return the final solution
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int waysForPairwiseSumToBeK( int N, int K)
{
int dp[N+1][K+1][3];
memset (dp, 0, sizeof dp);
for ( int i = 0; i <= N; i++) {
for ( int rem = 0; rem <= K; rem++) {
for ( int previous = 0; previous <= 2; previous++) {
if (i == 0) {
if (rem == 0) dp[i][rem][previous] = 1;
else dp[i][rem][previous] = 0;
}
else {
int ways = 0;
ways += dp[i-1][rem][0];
if (rem - previous >= 0)
ways += dp[i-1][rem-previous][1];
if (rem - (2 * previous) >= 0)
ways += dp[i-1][rem-(2*previous)][2];
dp[i][rem][previous] = ways;
}
}
}
}
return dp[N][K][0];
}
int main()
{
int N = 4, K = 3;
int totWays = waysForPairwiseSumToBeK(N, K);
cout << totWays << ' ' ;
return 0;
}
|
Java
public class PairwiseSum {
static int waysForPairwiseSumToBeK( int N, int K) {
int [][][] dp = new int [N + 1 ][K + 1 ][ 3 ];
for ( int i = 0 ; i <= N; i++) {
for ( int rem = 0 ; rem <= K; rem++) {
for ( int previous = 0 ; previous <= 2 ; previous++) {
dp[i][rem][previous] = 0 ;
}
}
}
for ( int i = 0 ; i <= N; i++) {
for ( int rem = 0 ; rem <= K; rem++) {
for ( int previous = 0 ; previous <= 2 ; previous++) {
if (i == 0 ) {
if (rem == 0 ) dp[i][rem][previous] = 1 ;
else dp[i][rem][previous] = 0 ;
} else {
int ways = 0 ;
ways += dp[i - 1 ][rem][ 0 ];
if (rem - previous >= 0 )
ways += dp[i - 1 ][rem - previous][ 1 ];
if (rem - ( 2 * previous) >= 0 )
ways += dp[i - 1 ][rem - ( 2 * previous)][ 2 ];
dp[i][rem][previous] = ways;
}
}
}
}
return dp[N][K][ 0 ];
}
public static void main(String[] args) {
int N = 4 , K = 3 ;
int totWays = waysForPairwiseSumToBeK(N, K);
System.out.println(totWays);
}
}
|
Python3
def waysForPairwiseSumToBeK(N, K):
dp = [[[ 0 for _ in range ( 3 )] for _ in range (K + 1 )] for _ in range (N + 1 )]
for i in range (N + 1 ):
for rem in range (K + 1 ):
for previous in range ( 3 ):
if i = = 0 :
if rem = = 0 :
dp[i][rem][previous] = 1
else :
dp[i][rem][previous] = 0
else :
ways = 0
ways + = dp[i - 1 ][rem][ 0 ]
if rem - previous > = 0 :
ways + = dp[i - 1 ][rem - previous][ 1 ]
if rem - ( 2 * previous) > = 0 :
ways + = dp[i - 1 ][rem - ( 2 * previous)][ 2 ]
dp[i][rem][previous] = ways
return dp[N][K][ 0 ]
N = 4
K = 3
totWays = waysForPairwiseSumToBeK(N, K)
print (totWays)
|
C#
using System;
public class PairwiseSum
{
static int WaysForPairwiseSumToBeK( int N, int K)
{
int [,,] dp = new int [N + 1, K + 1, 3];
for ( int i = 0; i <= N; i++)
{
for ( int rem = 0; rem <= K; rem++)
{
for ( int previous = 0; previous <= 2; previous++)
{
dp[i, rem, previous] = 0;
}
}
}
for ( int i = 0; i <= N; i++)
{
for ( int rem = 0; rem <= K; rem++)
{
for ( int previous = 0; previous <= 2; previous++)
{
if (i == 0)
{
if (rem == 0) dp[i, rem, previous] = 1;
else dp[i, rem, previous] = 0;
}
else
{
int ways = 0;
ways += dp[i - 1, rem, 0];
if (rem - previous >= 0)
ways += dp[i - 1, rem - previous, 1];
if (rem - (2 * previous) >= 0)
ways += dp[i - 1, rem - (2 * previous), 2];
dp[i, rem, previous] = ways;
}
}
}
}
return dp[N, K, 0];
}
public static void Main( string [] args)
{
int N = 4, K = 3;
int totWays = WaysForPairwiseSumToBeK(N, K);
Console.WriteLine(totWays);
}
}
|
Javascript
function waysForPairwiseSumToBeK(N, K) {
let dp = new Array(N + 1).fill(0).map(() => new Array(K + 1).fill(0).map(() => new Array(3).fill(0)));
for (let i = 0; i <= N; i++) {
for (let rem = 0; rem <= K; rem++) {
for (let previous = 0; previous <= 2; previous++) {
if (i == 0) {
if (rem == 0) dp[i][rem][previous] = 1;
else dp[i][rem][previous] = 0;
} else {
let ways = 0;
ways += dp[i - 1][rem][0];
if (rem - previous >= 0)
ways += dp[i - 1][rem - previous][1];
if (rem - (2 * previous) >= 0)
ways += dp[i - 1][rem - (2 * previous)][2];
dp[i][rem][previous] = ways;
}
}
}
}
return dp[N][K][0];
}
let N = 4,
K = 3;
let totWays = waysForPairwiseSumToBeK(N, K);
console.log(totWays);
|
Time Complexity: O(N*K)
Auxiliary Space: O(N*K)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...