删数方案数(regex)

[题目描述]

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

[输入文件]

第一行 n 个正整数

以下有 n行,每行1个

正整数表示整数序列a

[输出文件]

一个整数表示答案

[输入样例]

4

1 2 3 4

[输出样例]

3

[数据范围]

30%:n<=5

100%:n<=20

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

题解:

对于前半部分和后半部分dfs枚举

将前半部分得到的值包括状态存进hash(去重),在把后半部分的所有状态去重在hash中查找

本来是用的三进制数表示存进子集A,存进子集B,删去3种状态,后面发现没有必要

因为是“删数的方案”,也就是除删去的数,AB集合间如何分配并不关心,所以直接二进制就行

注意hash不能只存值,还要保存二进制数以判重,保存二进制数的数组不能太小也不能大

hash的大小70000够了,状态数组zt[70000][700]正好AC,500则90分,100则75分

博客里上传了数据,在管理里的文件

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 struct Node
 7 {
 8     long long s;
 9     int p;
10 }f[70001];
11 int n,zt[70001][701],len,h[1200001];
12 long long ans,has[70001],sp[70001],inf,a[21];
13 bool cmp(Node a,Node b)
14 {
15     return (a.s<b.s||(a.s==b.s&&a.p<b.p));
16 }
17 void push_hash(long long x,int i)
18 {int j;
19     long long p=(x+1000000000)%70000;
20      while (has[p]!=inf&&has[p]!=x)
21      {
22             p++;
23             if (p>70000) p=1;
24      }
25      if (has[p]==inf)
26      {
27         has[p]=x;
28         sp[p]=1;
29         zt[p][sp[p]]=i;
30      }
31      else if (has[p]==x)
32      {
33         for (j=1;j<=sp[p];j++)
34          if (i==zt[p][j]) return;
35          sp[p]++;
36          zt[p][sp[p]]=i;
37      }
38 }
39 void ask_hash(long long x,int i)
40 {int j;
41     long long p=(x+1000000000)%70000;
42      while (has[p]!=inf&&has[p]!=x)
43      {
44             p++;
45             if (p>70000) p=1;
46      }
47      if (has[p]==x)
48      {
49         for (j=1;j<=sp[p];j++)
50         h[zt[p][j]|i]=1;
51      }
52 }
53 void dfs1(int x,long long s,int p)
54 {int i;
55     if (x>n/2) push_hash(s,p);
56     else 
57     for (i=-1;i<=1;i++)
58     dfs1(x+1,s+i*a[x],p|((i!=0)<<(x-1)));
59 }
60 void dfs2(int x,long long s,int p)
61 {int i;
62     if (x>n) f[++len]=(Node){s,p};
63     else 
64     for (i=-1;i<=1;i++)
65     dfs2(x+1,s+i*a[x],p|((i!=0)<<(x-1)));
66 }
67 int main()
68 {int i,j;
69 long long s;
70 freopen("regex.in","r",stdin);
71 freopen("regex.out","w",stdout);
72     cin>>n;
73     memset(has,-127,sizeof(has));
74     inf=has[0];
75     for (i=1;i<=n;i++)
76      scanf("%lld",&a[i]);
77     dfs1(1,0,0);dfs2(n/2+1,0,0);
78     sort(f+1,f+len+1,cmp);
79      for (i=1;i<len;i++)
80       if (f[i].s==f[i+1].s&&f[i].p==f[i+1].p) f[i].s=(1<<30);
81     sort(f+1,f+len+1,cmp);
82     while (f[len].s==(1<<30)) len--;
83     for (i=1;i<=len;i++)
84     ask_hash(-f[i].s,f[i].p);
85     for (i=1;i<=(1<<n)-1;i++) ans+=h[i];
86     //cout<<h[i]<<endl;
87     cout<<ans;
88 }

 

posted @ 2017-08-14 15:24  Z-Y-Y-S  阅读(390)  评论(0编辑  收藏  举报