Given is an array arr[] of size n. Return the number of non-empty subsequences such that the product of all in the subsequence is power of 2. Since the answer may be too large, return it modulo 109 + 7.
Examples:
Input: arr[] = [1, 2, 3]
Output: 3
Explanation: There are 3 such subsequences [1], [2] and [1, 2].Input: arr[] = [3, 5, 9]
Output: 0
Explanation: There is no such subsequence.
Table of Content
[Naive Approach] Generate All Subsequences - O(n⨯2n) Time and O(n) Space
The most basic approach is to generate all possible non-empty subsequences of the given array, calculate the product of each subsequence, and check if the resulting product is a power of 2.
- Generate all 2n subsequences using recursion..
- For each subsequence, multiply its elements.
- To check if this product is a power of 2, we continuously divide it by 2 as long as it is even. If we eventually reach 1, it is a power of 2.
- Keep a count of valid subsequences (subtracting 1 because recursion will count 1 empty subsequence) and return it modulo 109 + 7.
#include <iostream>
#include <vector>
using namespace std;
int MOD = 1e9 + 7;
// checks if a number is a power of 2
// by repeatedly dividing it by 2
bool isPowerOfTwo(int n)
{
if (n <= 0)
return false;
while (n % 2 == 0)
{
n /= 2;
}
// if n divided down to 1, it's a power of 2
return n == 1;
}
int genSubseq(int idx, int product, vector<int> &arr)
{
// base Case
if (idx == arr.size())
{
// only count subsequences that evaluate
// to a power of 2
if (isPowerOfTwo(product))
return 1;
else
return 0;
}
int count = 0;
// Option 1: Exclude the current element
count = (count +
genSubseq(idx + 1, product, arr))
% MOD;
// Option 2: Include the current element
count = (count +
genSubseq(idx + 1, product * arr[idx], arr))
% MOD;
return count;
}
int numberOfSubsequences(vector<int> &arr)
{
// start recursion from index 0, initial product 1,
// to check all possible subsequences
int count = genSubseq(0, 1, arr);
// return count-1 because there will be one
// empty subsequence
return count - 1;
}
int main()
{
vector<int> arr = {1, 2, 3};
cout << numberOfSubsequences(arr) << endl;
return 0;
}
public class Solution {
int MOD = 1000000007;
// checks if a number is a power of 2
// by repeatedly dividing it by 2
boolean isPowerOfTwo(int n)
{
if (n <= 0)
return false;
while (n % 2 == 0) {
n /= 2;
}
// if n divided down to 1, it's a power of 2
return n == 1;
}
int genSubseq(int idx, int product, int[] arr)
{
// base Case
if (idx == arr.length) {
// only count subsequences that evaluate
// to a power of 2
if (isPowerOfTwo(product))
return 1;
else
return 0;
}
int count = 0;
// Option 1: Exclude the current element
count = (count + genSubseq(idx + 1, product, arr))
% MOD;
// Option 2: Include the current element
count = (count
+ genSubseq(idx + 1, product * arr[idx],
arr))
% MOD;
return count;
}
public int numberOfSubsequences(int[] arr)
{
// start recursion from index 0, initial product 1,
// to check all possible subsequences
int count = genSubseq(0, 1, arr);
// return count-1 because there will be one
// empty subsequence
return count - 1;
}
public static void main(String[] args)
{
int[] arr = { 1, 2, 3 };
Solution sol = new Solution();
System.out.println(sol.numberOfSubsequences(arr));
}
}
class Solution:
def __init__(self):
self.MOD = 10**9 + 7
# checks if a number is a power of 2
# by repeatedly dividing it by 2
def isPowerOfTwo(self, n):
if n <= 0:
return False
while n % 2 == 0:
n //= 2
# if n divided down to 1, it's a power of 2
return n == 1
def genSubseq(self, idx, product, arr):
# base Case
if idx == len(arr):
# only count subsequences that evaluate
# to a power of 2
if self.isPowerOfTwo(product):
return 1
else:
return 0
count = 0
# Option 1: Exclude the current element
count = (count +
self.genSubseq(idx + 1, product, arr)) \
% self.MOD
# Option 2: Include the current element
count = (count +
self.genSubseq(idx + 1, product * arr[idx], arr)) \
% self.MOD
return count
def numberOfSubsequences(self, arr):
# start recursion from index 0, initial product 1,
# to check all possible subsequences
count = self.genSubseq(0, 1, arr)
# return count-1 because there will be one
# empty subsequence
return count - 1
if __name__ == "__main__":
arr = [1, 2, 3]
sol = Solution()
print(sol.numberOfSubsequences(arr))
using System;
public class Solution {
int MOD = 1000000007;
// checks if a number is a power of 2
// by repeatedly dividing it by 2
bool isPowerOfTwo(int n)
{
if (n <= 0)
return false;
while (n % 2 == 0) {
n /= 2;
}
// if n divided down to 1, it's a power of 2
return n == 1;
}
int genSubseq(int idx, int product, int[] arr)
{
// base Case
if (idx == arr.Length) {
// only count subsequences that evaluate
// to a power of 2
if (isPowerOfTwo(product))
return 1;
else
return 0;
}
int count = 0;
// Option 1: Exclude the current element
count = (count + genSubseq(idx + 1, product, arr))
% MOD;
// Option 2: Include the current element
count = (count
+ genSubseq(idx + 1, product * arr[idx],
arr))
% MOD;
return count;
}
public int numberOfSubsequences(int[] arr)
{
// start recursion from index 0, initial product 1,
// to check all possible subsequences
int count = genSubseq(0, 1, arr);
// return count-1 because there will be one
// empty subsequence
return count - 1;
}
public static void Main()
{
int[] arr = { 1, 2, 3 };
Solution sol = new Solution();
Console.WriteLine(sol.numberOfSubsequences(arr));
}
}
class Solution {
constructor() {
this.MOD = 1000000007;
}
// checks if a number is a power of 2
// by repeatedly dividing it by 2
isPowerOfTwo(n)
{
if (n <= 0)
return false;
while (n % 2 === 0) {
n = Math.floor(n / 2);
}
// if n divided down to 1, it's a power of 2
return n === 1;
}
genSubseq(idx, product, arr)
{
// base Case
if (idx === arr.length) {
// only count subsequences that evaluate
// to a power of 2
if (this.isPowerOfTwo(product))
return 1;
else
return 0;
}
let count = 0;
// Option 1: Exclude the current element
count
= (count + this.genSubseq(idx + 1, product, arr)) % this.MOD;
// Option 2: Include the current element
count = (count
+ this.genSubseq(idx + 1, product * arr[idx], arr))
% this.MOD;
return count;
}
numberOfSubsequences(arr)
{
// start recursion from index 0, initial product 1,
// to check all possible subsequences
let count = this.genSubseq(0, 1, arr);
// return count-1 because there will be one
// empty subsequence
return count - 1;
}
}
const arr = [ 1, 2, 3 ];
const sol = new Solution();
console.log(sol.numberOfSubsequences(arr));
Output
3
[Expected Approach] Mathematical Property with Bitwise AND - O(n) Time and O(1) Space
Product is a power of 2 if and only if every element in the product is a power of 2. We count how many numbers in the array are powers of 2. If there are C such numbers, the number of non-empty combinations we can form is 2C-1
How to check for a Power of 2:
- Using Division : We can repeatedly divide the number by 2 as long as it is even. If we eventually reach 1, it is a power of 2. This takes O(log n) time per element.
- Using Bitwise AND : If we write down the powers of 2 in binary, they always have exactly one set bit (e.g., 4 is 1002, 8 is 10002). Because of this, applying x & (x -1 ) to a power of 2 will always result in 0. This gives us a fast, O(1) way to identify valid elements.
Implementation:
- Initialize a counter count = 0
- Traverse the array element by element.
- For each element, check if it is a power of 2. We can do this using the Bitwise AND :num > 0 and num & (num - 1) == 0.
- If it is a power of 2, increment
count. - Calculate total subsequences using (2C - 1) %(109 + 7).
Consider arr[] = [1, 2, 3, 4, 6]
Step 1: Count elements that are powers of 2
- arr[0] = 1, Bitwise check: 1 & 0 == 0 → Valid! → count = 1
- arr[1] = 2, Bitwise check: 2 & 1 == 0 → Valid! → count = 2
- arr[2] = 3, Bitwise check: 3 & 2 != 0 → Invalid! → count = 2
- arr[3] = 4, Bitwise check: 4 & 3 == 0 → Valid! → count = 3
- arr[4] = 6, Bitwise check: 6 & 5 !=0 → Invalid! → count = 3
Step 2: Calculate combinations
- Total valid elements found:
count = 3(The elements are{1, 2, 4}). - Total valid subsequences = (23) - 1 = 7
These 7 valid subsequences are : [1], [2], [4], [1, 2], [1, 4], [2, 4], [1, 2, 4], product for there elements is power of 2.
#include <iostream>
#include <vector>
using namespace std;
int MOD = 1e9 + 7;
// function to calculate (base^exp) % MOD
int power(int base, int exp)
{
int res = 1;
base = base % MOD;
while (exp > 0)
{
// if the current exponent bit is odd,
// multiply the base to our result
if (exp % 2 == 1)
res = (res * 1LL * base) % MOD;
// divide exponent by 2 (bit shift)
// and square the base
exp = exp >> 1;
base = (base * 1LL * base) % MOD;
}
return res;
}
int numberOfSubsequences(vector<int> &arr)
{
int count = 0;
// count elements that are powers of 2 using Bitwise AND
for (int num : arr)
{
if (num > 0 && (num & (num - 1)) == 0)
{
count++;
}
}
// total subsequences (2^C) - 1, we subtract 1
// because there will be empty subsequence
int total = power(2, count);
return (total - 1 + MOD) % MOD;
}
int main()
{
vector<int> arr = {1, 2, 3};
cout << numberOfSubsequences(arr) << endl;
return 0;
}
public class Solution {
int MOD = 1000000007;
// function to calculate (base^exp) % MOD
int power(int baseVal, int exp) {
int res = 1;
baseVal = baseVal % MOD;
while (exp > 0) {
// if the current exponent bit is odd,
// multiply the base to our result
if (exp % 2 == 1)
res = (int) (res * 1L * baseVal % MOD);
// divide exponent by 2 (bit shift)
// and square the base
exp = exp >> 1;
baseVal = (int) (baseVal * 1L * baseVal % MOD);
}
return res;
}
public int numberOfSubsequences(int[] arr) {
int count = 0;
// count elements that are powers of 2 using Bitwise AND
for (int num : arr) {
if (num > 0 && (num & (num - 1)) == 0) {
count++;
}
}
// total subsequences (2^C) - 1, we subtract 1
// because there will be empty subsequence
int total = power(2, count);
return (total - 1 + MOD) % MOD;
}
public static void main(String[] args) {
int[] arr = {1, 2, 3};
Solution sol = new Solution();
System.out.println(sol.numberOfSubsequences(arr));
}
}
class Solution:
def __init__(self):
self.MOD = 10**9 + 7
# function to calculate (base^exp) % MOD
def power(self, base, exp):
res = 1
base = base % self.MOD
while exp > 0:
# if the current exponent bit is odd,
# multiply the base to our result
if exp % 2 == 1:
res = (res * base) % self.MOD
# divide exponent by 2 (bit shift)
# and square the base
exp = exp >> 1
base = (base * base) % self.MOD
return res
def numberOfSubsequences(self, arr):
count = 0
# count elements that are powers of 2 using Bitwise AND
for num in arr:
if num > 0 and (num & (num - 1)) == 0:
count += 1
# total subsequences (2^C) - 1, we subtract 1
# because there will be empty subsequence
total = self.power(2, count)
return (total - 1 + self.MOD) % self.MOD
if __name__ == "__main__":
arr = [1, 2, 3]
sol = Solution()
print(sol.numberOfSubsequences(arr))
using System;
public class Solution {
int MOD = 1000000007;
// function to calculate (base^exp) % MOD
int power(int baseVal, int exp) {
int res = 1;
baseVal = baseVal % MOD;
while (exp > 0) {
// if the current exponent bit is odd,
// multiply the base to our result
if (exp % 2 == 1)
res = (int) (res * 1L * baseVal % MOD);
// divide exponent by 2 (bit shift)
// and square the base
exp = exp >> 1;
baseVal = (int) (baseVal * 1L * baseVal % MOD);
}
return res;
}
public int numberOfSubsequences(int[] arr) {
int count = 0;
// count elements that are powers of 2 using Bitwise AND
foreach (int num in arr) {
if (num > 0 && (num & (num - 1)) == 0) {
count++;
}
}
// total subsequences (2^C) - 1, we subtract 1
// because there will be empty subsequence
int total = power(2, count);
return (total - 1 + MOD) % MOD;
}
public static void Main() {
int[] arr = {1, 2, 3};
Solution sol = new Solution();
Console.WriteLine(sol.numberOfSubsequences(arr));
}
}
class Solution {
constructor() {
this.MOD = 1000000007;
}
// function to calculate (base^exp) % MOD
power(base, exp) {
let res = 1;
base = base % this.MOD;
while (exp > 0) {
// if the current exponent bit is odd,
// multiply the base to our result
if (exp % 2 === 1)
res = Number((BigInt(res) * BigInt(base)) % BigInt(this.MOD));
// divide exponent by 2 (bit shift)
// and square the base
exp = exp >> 1;
base = Number((BigInt(base) * BigInt(base)) % BigInt(this.MOD));
}
return res;
}
numberOfSubsequences(arr) {
let count = 0;
// count elements that are powers of 2 using Bitwise AND
for (let num of arr) {
if (num > 0 && (num & (num - 1)) === 0) {
count++;
}
}
// total subsequences (2^C) - 1, we subtract 1
// because there will be empty subsequence
let total = this.power(2, count);
return (total - 1 + this.MOD) % this.MOD;
}
}
const arr = [1, 2, 3];
const sol = new Solution();
console.log(sol.numberOfSubsequences(arr));
Output
3