Skip to content
Related Articles

Related Articles

Sum of products of all possible K size subsets of the given array
  • Difficulty Level : Hard
  • Last Updated : 02 Feb, 2021
GeeksforGeeks - Summer Carnival Banner

Given an array arr[] of N non-negative integers and an integer 1 ≤ K ≤ N. The task is to find the sum of the products of all possible subsets of arr[] of size K

Examples: 

Input: arr[] = {1, 2, 3, 4}, K = 2 
Output: 35 
(1 * 2) + (1 * 3) + (1 * 4) + (2 * 3) + (2 * 4) 
+ (3 * 4) = 2 + 3 + 4 + 6 + 8 + 12 = 35

Input: arr[] = {1, 2, 3, 4}, K = 3 
Output: 50 

Naive approach: Generate all possible subsets of size K and find the resultant product of each subset. Then sum the product obtained for each subset. The time complexity of this solution would be exponential.



C++




// Program  find the sum of the products of all possible
// subsets of arr[] of size K.
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
 
// using these variable , to avoid many parameters in a
// recusrive function , which will reduce the speed of
// the program
int K, N;
 
// it returns sum of all the multiplied Subset
int getSum(vector<vector<int> > res)
{
    long long sum = 0, MOD = 1000000007;
 
    for (vector<int> tempList : res) {
 
        long long tempSum = 1;
 
        for (int val : tempList) {
 
            tempSum = (tempSum * val) % MOD;
        }
 
        sum = sum + tempSum;
    }
    // we are doing % operation  , so that our result
    // should not get overflow
    return sum % MOD;
}
 
// Generate all Subsrray with size K
void createAllPossibleSubset(int arr[],
                             vector<vector<int> >& res,
                             vector<int>& temp, int index)
{
    /*
      when we get the required size subset , we
      add into the result list and return
    */
    if (temp.size() == K) {
        res.push_back(temp);
        return;
    }
 
    // otherwise we add current element ,
    // and move forward to add next element in our
    // subset
    for (int i = index; i < N; i++) {
        temp.push_back(arr[i]);
 
        createAllPossibleSubset(arr, res, temp, i + 1);
 
        // removing the last element , for backtracking
        temp.pop_back();
    }
}
 
 
int sumOfProduct(int arr[], int n, int k)
{
    K = k;
    N = n;
 
    // result store all the subset of size K
    vector<vector<int> > res;
    vector<int> temp;
 
    createAllPossibleSubset(arr, res, temp, 0);
 
    return getSum(res);
}
 
 
// Driver code
int main()
{
    int n = 4, k = 2;
    int arr[] = { 1, 2, 3, 4 };
    cout << sumOfProduct(arr, n, k);
    return 0;
}
// This code is contributed by Pradeep Mondal P

Java




// Program  find the sum of the products of all possible
// subsets of arr[] of size K.
 
import java.io.*;
import java.util.*;
 
class GFG {
 
    // storing the k value , so that it can be easily
    // accessed
    static int K;
 
    public static int sumOfProduct(int arr[], int n, int k)
    {
        K = k;
 
        // result store all the subset of size K
        ArrayList<ArrayList<Integer> > res
            = new ArrayList<>();
 
        createAllPossibleSubset(arr, res, new ArrayList<>(),
                                0);
 
        return getSum(res);
    }
 
    // Generate all Subsrray with size K
    static void createAllPossibleSubset(
        int arr[], ArrayList<ArrayList<Integer> > res,
        ArrayList<Integer> temp, int index)
    {
        /*
          when we get the required size subset , we
          add into the result list and return
        */
        if (temp.size() == K) {
            res.add(new ArrayList<>(temp));
            return;
        }
 
        // otherwise we add current element ,
        // and move forward to add next element in our
        // subset
        for (int i = index; i < arr.length; i++) {
            temp.add(arr[i]);
 
            createAllPossibleSubset(arr, res, temp, i + 1);
 
            // removing the last element , for backtracking
            temp.remove(temp.size() - 1);
        }
    }
 
    // it returns sum of all the multiplied Subset
    private static int
    getSum(ArrayList<ArrayList<Integer> > res)
    {
 
        int sum = 0, MOD = 1000000007;
        for (ArrayList<Integer> tempList : res) {
           
            long tempSum = 1;
            for (int val : tempList) {
               
                tempSum *= val % MOD;
            }
 
            sum += tempSum;
        }
        // we are doing % operation  , so that our result
        // should not get overflow
        return sum % MOD;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int n = 4, k = 2;
        int arr[] = { 1, 2, 3, 4 };
        System.out.println(sumOfProduct(arr, n, k));
    }
}
// This code is Contributed by Pradeep Mondal P

Output :  

35

Time Complexity:   2n
Auxiliary Space:  2n  ( n   is the array size )

Efficient approach: Take the example of an array a[] = {1, 2, 3} and K = 3. Then, 

k = 1, answer = 1 + 2 + 3 = 6 
k = 2, answer = 1 * (2 + 3) + 2 * 3 + 0 = 11 
k = 3, answer = 1 * (2 * 3 + 0) + 0 + 0 = 6 
 

In the example, if the contribution of 1 is needed to be obtained in the answer for K = 2 then the sum of all elements after the index of element 1 is required in the previously computed values for K = 1. It can be seen that the sum of elements 2 and 3 is required. Thus, for any K, the answer obtained for K – 1 is required. 

So, bottom up dynamic programming approach can be used to solve this problem. Create a table dp[][] and fill it in bottom up manner where dp[i][j] will store the contribution of an element arr[j – 1] to the answer for K = i. Hence, the recurrence relation will be, 

dp[i][j] = arr[j-1] * \sum_{k=j+1}^{n}
dp[i-1][k]
answer[k] = \sum_{i=1}^{n}
dp[k][i] 

Below is the implementation of the above approach: 

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to return the sum of products of
// all the possible k size subsets
int sumOfProduct(int arr[], int n, int k)
{
    // Initialising all the values to 0
    int dp[n + 1][n + 1] = { 0 };
 
    // To store the answer for
    // current value of k
    int cur_sum = 0;
 
    // For k = 1, the answer will simply
    // be the sum of all the elements
    for (int i = 1; i <= n; i++) {
        dp[1][i] = arr[i - 1];
        cur_sum += arr[i - 1];
    }
 
    // Filling the table in bottom up manner
    for (int i = 2; i <= k; i++) {
 
        // To store the elements of the current
        // row so that we will be able to use this sum
        // for subsequent values of k
        int temp_sum = 0;
 
        for (int j = 1; j <= n; j++) {
 
            // We will subtract previously computed value
            // so as to get the sum of elements from j + 1
            // to n in the (i - 1)th row
            cur_sum -= dp[i - 1][j];
 
            dp[i][j] = arr[j - 1] * cur_sum;
            temp_sum += dp[i][j];
        }
        cur_sum = temp_sum;
    }
    return cur_sum;
}
 
// Driver code
int main()
{
    int arr[] = { 1, 2, 3, 4 };
    int n = sizeof(arr) / sizeof(int);
    int k = 2;
 
    cout << sumOfProduct(arr, n, k);
 
    return 0;
}

Java




// Java implementation of the approach
import java.util.*;
 
class GFG{
 
// Function to return the sum of products of
// all the possible k size subsets
static int sumOfProduct(int arr[], int n,
                        int k)
{
    int dp[][] = new int[n + 1][n + 1];
     
    // Initialising all the values to 0
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= n; j++)
            dp[i][j] = 0;
 
    // To store the answer for
    // current value of k
    int cur_sum = 0;
 
    // For k = 1, the answer will simply
    // be the sum of all the elements
    for(int i = 1; i <= n; i++)
    {
        dp[1][i] = arr[i - 1];
        cur_sum += arr[i - 1];
    }
 
    // Filling the table in bottom
    // up manner
    for(int i = 2; i <= k; i++)
    {
         
        // To store the elements of the
        // current row so that we will
        // be able to use this sum
        // for subsequent values of k
        int temp_sum = 0;
 
        for(int j = 1; j <= n; j++)
        {
             
            // We will subtract previously
            // computed value  so as to get
            // the sum of elements from j + 1
            // to n in the (i - 1)th row
            cur_sum -= dp[i - 1][j];
 
            dp[i][j] = arr[j - 1] * cur_sum;
            temp_sum += dp[i][j];
        }
        cur_sum = temp_sum;
    }
    return cur_sum;
}
 
// Driver code
public static void main(String[] args)
{
    int arr[] = { 1, 2, 3, 4 };
    int n = arr.length;
    int k = 2;
 
    System.out.print(sumOfProduct(arr, n, k)); 
}
}
 
// This code is contributed by Stream_Cipher

Python3




# Python3 implementation of the approach
  
# Function to return the sum of products of
# all the possible k size subsets
def sumOfProduct(arr, n, k):
     
    # Initialising all the values to 0
    dp = [ [ 0 for x in range(n + 1)] for y in range(n + 1)]
     
    # To store the answer for
    # current value of k
    cur_sum = 0
     
    # For k = 1, the answer will simply
    # be the sum of all the elements
    for i in range(1, n + 1):
        dp[1][i] = arr[i - 1]
        cur_sum += arr[i - 1]
  
    # Filling the table in bottom up manner
    for i in range(2 , k + 1):
  
        # To store the elements of the current
        # row so that we will be able to use this sum
        # for subsequent values of k
        temp_sum = 0
  
        for j in range( 1,  n + 1):
  
            # We will subtract previously computed value
            # so as to get the sum of elements from j + 1
            # to n in the (i - 1)th row
            cur_sum -= dp[i - 1][j]
  
            dp[i][j] = arr[j - 1] * cur_sum
            temp_sum += dp[i][j]
        cur_sum = temp_sum
    return cur_sum
  
# Driver code
if __name__ == "__main__":
     
    arr = [ 1, 2, 3, 4 ]
    n = len(arr)
    k = 2
    print(sumOfProduct(arr, n, k))
 
# This code is contributed by chitranayal

C#




// C# implementation of the approach
using System.Collections.Generic;
using System;
 
class GFG{
 
// Function to return the sum of products of
// all the possible k size subsets
static int sumOfProduct(int []arr, int n, int k)
{
    int [,]dp = new int[n + 1, n + 1];
     
    // Initialising all the values to 0
    for(int i = 0; i <= n; i++)
        for(int j = 0; j <= n; j++)
            dp[i, j] = 0;
 
    // To store the answer for
    // current value of k
    int cur_sum = 0;
 
    // For k = 1, the answer will simply
    // be the sum of all the elements
    for(int i = 1; i <= n; i++)
    {
        dp[1, i] = arr[i - 1];
        cur_sum += arr[i - 1];
    }
 
    // Filling the table in bottom up manner
    for(int i = 2; i <= k; i++)
    {
         
        // To store the elements of the
        // current row so that we will
        // be able to use this sum
        // for subsequent values of k
        int temp_sum = 0;
 
        for(int j = 1; j <= n; j++)
        {
             
            // We will subtract previously
            // computed value so as to get
            // the sum of elements from j + 1
            // to n in the (i - 1)th row
            cur_sum -= dp[i - 1, j];
 
            dp[i, j] = arr[j - 1] * cur_sum;
            temp_sum += dp[i, j];
        }
        cur_sum = temp_sum;
    }
    return cur_sum;
}
 
// Driver code
public static void Main()
{
    int []arr = { 1, 2, 3, 4 };
    int n = arr.Length;
    int k = 2;
 
    Console.WriteLine(sumOfProduct(arr, n, k)); 
}
}
 
// This code is contributed by Stream_Cipher

Output:

35

Time Complexity: O(N2)
 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up
Recommended Articles
Page :