Description
There are N people in the summer camp, and their strength is M(i). Please select a number of people from these N individuals. If these people can be divided into two groups and the sum of the two groups is equal, it is called a legal election. How many legal elections are there?
Input
The first line is an integer N, indicating the number of people.
Next N lines, one integer M(i) per line
Output
Output an integer line by line, indicating the total number of options.
Sample Input
4
1
2
3
4
Sample Output
3
Example explanation:
The first is to select {1,2,3} and divide it into {1,2} and {3} groups;
The second is to select {1,3,4} and divide it into {1,3} and {4} groups;
The third one is {1,2,3,4} and divided into {1,4} and {2,3} groups.
Data Constraint
40% of the data meet the following requirements: 1 < = m (I) < 1000;
For 100% of data, 2 < = n < = 20,1 < = m (I) < = 100000000
Solving problems
Half search: search from 1 to n/2, select group A for each, select group B for each, do not select three options, record the sum and status, search the same operation once for n/2+1 ~ n, and then arrange the order to count the answers.
Code
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int MAXN = 25;
typedef long long LL;
struct Data{
LL sum;
LL S;
}data1[1<<20],data2[1<<20];
int a[MAXN],n,k,cnt1,cnt2,ans;
bool vis[(1<<20)+2000];
inline void dfs1(int x,int Sum,int s){
if(x==k+1) {
data1[++cnt1].S=s;
data1[cnt1].sum=Sum;
return ;
}
dfs1(x+1,Sum+a[x],s+(1<<(n-x)));
dfs1(x+1,Sum-a[x],s+(1<<(n-x)));
dfs1(x+1,Sum,s);
}
inline void dfs2(int x,int Sum,int s){
if(x==n+1){
data2[++cnt2].S=s;
data2[cnt2].sum=Sum;
return ;
}
dfs2(x+1,Sum+a[x],s+(1<<(n-x)));
dfs2(x+1,Sum-a[x],s+(1<<(n-x)));
dfs2(x+1,Sum,s);
}
inline bool cmp(Data A,Data B){
return A.sum<B.sum;
}
int main(){
freopen("subset.in","r",stdin);
freopen("subset.out","w",stdout);
scanf("%d",&n);
for(register int i=1;i<=n;i++) scanf("%d",&a[i]);
k=n/2;dfs1(1,0,0);dfs2(k+1,0,0);
sort(data1+1,data1+1+cnt1,cmp);
sort(data2+1,data2+1+cnt2,cmp);
int i=1,j=1;data1[++cnt1].sum=data2[++cnt2].sum=1e9;
while(i<cnt1 && j<cnt2){
if(data1[i].sum<data2[j].sum) i++;
else if(data1[i].sum>data2[j].sum) j++;
else {
int l1=i,r1=i,l2=j,r2=j;
while(data1[r1].sum==data1[l1].sum) r1++;
while(data2[r2].sum==data2[l2].sum) r2++;
for(register int p=l1;p<r1;p++)
for(register int q=l2;q<r2;q++){
if(vis[data1[p].S+data2[q].S]) continue;
ans++;vis[data1[p].S+data2[q].S]=1;
}
i=r1,j=r2;
}
}cout<<ans-1<<endl;
return 0;
}