Divide the input array into two equal parts: t_1, t_2, ..., t_{n/2} and t_{n/2+1}, t_{n/2+2}, ..., t_n. Store the first part in array and the second in array .
First, solve the problem for sequence . Iterate over all possible subsets of (there will be at most 2^{20} of them). For each subset, calculate the sum of its elements , and increment the value by . As the data structure , we can use, for example, an unordered_map. Thus, will contain the number of ways to choose a subset from array whose elements sum to .
Then, iterate over all subsets of array . Let be the sum of elements in one such subset. If we combine this subset with all subsets of array whose sum is equal to s - sum, the result will be a subset of the original array whose elements sum to .
Example
Let's consider the second example. Divide the input sequence into two parts:
a = (1, 3, 2),
b = (2 ,1, 4)
Iterate over all subsets of the set a = \{1, 3, 2\}:
\{1\}: sum = 1, m[1]++; | \{1, 2\}: sum = 3, m[3]++; |
\{3\}: sum = 3, m[3]++; | \{3, 2\}: sum = 5, m[5]++; |
\{2\}: sum = 2, m[2]++; | \{1, 3, 2\}: sum = 6, m[6]++; |
\{1, 3\}: sum = 4, m[4]++; | \{\}: sum = 0, m[0]++; |
The structure will contain the following values after processing:
Now, iterate over all subsets of the set b = \{2, 1, 4\}. In this example, the target sum is s = 7. For each sum corresponding to a subset of , add m[s - sum] to the final answer.
\{2\}: sum = 2, m[7 - 2] = m[5] = 1;
\{1\}: sum = 1, m[7 - 1] = m[6] = 1;
\{4\}: sum = 4, m[7 - 4] = m[3] = 2;
\{2, 1\}: sum = 3, m[7 - 3] = m[4] = 1;
\{2, 4\}: sum = 6, m[7 - 6] = m[1] = 1;
\{1, 4\}: sum = 5, m[7 - 5] = m[2] = 1;
\{2, 1, 4\}: sum = 7, m[7 - 7] = m[0] = 1;
\{\}: sum = 0, m[7 - 0] = m[7] = 0;
The target sum is 1 + 1 + 2 + 1 + 1 + 1 + 1 + 0 = 8, which is the final answer.
Algorithm implementation
Declare the data structures.
vector<int> a, b;
unordered_map<long long, long long> m;Read the input data. Store the first half of the sequence in array , and the second half in array .
scanf("%d %d", &n, &s);
a.resize(n / 2);
for (i = 0; i < n / 2; i++)
scanf("%d", &a[i]);
b.resize(n - n / 2);
for (i = n / 2; i < n; i++)
scanf("%d", &b[i - n / 2]);Iterate over all subsets of sequence and compute the sum of their elements. In the unordered_map structure, keep track of how many times each sum occurs among these subsets. If is the sum of the current subset, then increment by .
for (i = 0; i < (1 << a.size()); i++)
{
sum = 0;The variable contains the bitmask of the current subset of . The sum of its elements is computed in the variable .
for (j = 0; j < a.size(); j++)
if (i & (1 << j)) sum += a[j];For each obtained sum , increment the value of by .
m[sum]++;
}The number of ways to obtain the sum from the elements of the original array is counted in the variable .
res = 0;Iterate over all subsets of sequence .
for (i = 0; i < (1 << b.size()); i++)
{
sum = 0;The variable contains the bitmask of the current subset of . The sum of the elements in this subset is computed in the variable .
for (j = 0; j < b.size(); j++)
if (i & (1 << j)) sum += b[j];If we combine the current subset of set , whose sum of elements is , with all subsets of set a whose sum is s - sum, the result will be a subset of the original array whose sum of elements is equal to .
if (m.count(s - sum) > 0) res += m[s - sum];
}Print the answer.
printf("%lld\n", res);