[测试题]删数方案数

Description

给出一个正整数序列 a,长度为 n,cyb 不喜欢完美,他要删掉一些数(也可以不删,即删掉0个),但是他不会乱删,他希望删去以后,能将 a 分成 2 个集合,使得两个非空集合的数的和相同,现在他希望你能帮他算出删数的方案数。

Input

第一行 n 个正整数

以下有 n行,每行1个

正整数表示整数序列a

Output

一个整数表示答案

Sample Input

4

1 2 3 4

Sample Output

3

Hint

30%:n<=5

100%:n<=20

100%:a 中每个元素<=100000000

题解

涉及到了$hash$,状压,双向搜索
首先可以想出一个$3^N$的搜索.
枚举每个是不选还是在$A$集合,还是在$B$集合
这样显然通不过$20$的数据
那么我们发现这个搜索是独立的
如果在$A$集合,我们令其为$-1*a$
在$B$集合,令其为$1*a$
那么实际上我们在找一个方程有多少组解.
这样,我们先搜前面一半,将和用$hash$存起来
将选的情况,用一个$2$进制数也存入$hash$
这样可以通过全部数据

 1 #include<map>
 2 #include<cmath>
 3 #include<ctime>
 4 #include<queue>
 5 #include<stack>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<string>
 9 #include<cstdlib>
10 #include<cstring>
11 #include<iostream>
12 #include<algorithm>
13 #define LL long long
14 #define RE register
15 #define IL inline
16 using namespace std;
17 const int MOD=1e6+7;
18 
19 int n,lim;
20 int a[25];
21 int ans;
22 bool vis[(1<<21)+5];
23 struct HASH
24 {
25     int to,next,st;
26 }edge[MOD+5];
27 int path[MOD+5],top;
28 
29 void find_hash(int a,int st)
30 {
31     int k=(a%MOD+MOD)%MOD;
32     for (RE int i=path[k];i;i=edge[i].next) if (edge[i].to==a) vis[edge[i].st+st]=1;
33 }
34 void push_hash(int a,int st)
35 {
36     int k=(a%MOD+MOD)%MOD;
37     edge[++top].to=a;
38     edge[top].st=st;
39     edge[top].next=path[k];
40     path[k]=top;
41 }
42 
43 void Dfs(int cen,int tol,int set)
44 {
45     if (cen>lim)
46     {
47         push_hash(tol,set);
48         return;
49     }
50     Dfs(cen+1,tol,set);
51     Dfs(cen+1,tol+a[cen],set+(1<<cen-1));
52     Dfs(cen+1,tol-a[cen],set+(1<<cen-1));
53 }
54 void Dfs2(int cen,int tol,int set)
55 {
56     if (cen<=lim)
57     {
58         find_hash(tol,set);
59         return;
60     }
61     Dfs2(cen-1,tol,set);
62     Dfs2(cen-1,tol+a[cen],set+(1<<cen-1));
63     Dfs2(cen-1,tol-a[cen],set+(1<<cen-1));
64 }
65 
66 int main()
67 {
68     scanf("%d",&n);lim=n/2;
69     for (RE int i=1;i<=n;i++) scanf("%d",&a[i]);
70     Dfs(1,0,0);
71     Dfs2(n,0,0);
72     for (RE int i=1;i<(1<<n);i++) ans+=vis[i];
73     printf("%d",ans);
74     return 0;
75 }

 

posted @ 2017-08-14 16:24  NaVi_Awson  阅读(317)  评论(0)    收藏  举报