2017年8月7日提高组T1 选数

来源:互联网 发布:华为云计算培训 编辑:程序博客网 时间:2024/05/17 13:43

Description

给出n个数a[i],现在可以在其中任意选出若干个数,问有多少种选择方案,使得这几个数可以分成两个和相等的集合。

Input

第一行是一个正整数n,第二行每行n个正整数。

Output

输出一个数,表示方案数。

Sample Input

4
1 2 3 4
Sample Output

3
Hint

对于30%的数据,n<=10.
对于100%的数据,n<=20,a[i]<=100000000.
做法:注意到每个数的系数有三种情况,分别是0,1,-1。那么我们可以把序列分成长度相等的两部分,分别O(3^(n/2))搜索,排序后用双指针统计答案即可,统计时要注意判重。
代码如下:

#include <cstdio>#include <algorithm>#include <math.h>using namespace std;struct arr{    int x,y;}f[60007],ff[60007];int n,a[30],e=0,ee=0,ans;bool v[1024*1024+1];bool bobo;void dfs(int dep,int s,int ss){    if (s!=0)   bobo=1;    if (dep>n/2 && bobo)        {        if (s==0 && !v[ss])        {            v[ss]=1;            ans++;            e++;            f[e].y=s;            f[e].x=ss;        }        else        {            e++;            f[e].y=s;            f[e].x=ss;        }        return;             }    if (dep>n/2)    return;    dfs(dep+1,s,ss);    dfs(dep+1,s+a[dep],ss+pow(2,dep-1));    dfs(dep+1,s-a[dep],ss+pow(2,dep-1));}void dfs2(int dep,int s,int ss){    if (s!=0)   bobo=1;    if (dep>n && bobo)    {        ee++;        ff[ee].y=s;        ff[ee].x=ss;        if (s==0 && !v[ss])            {                v[ss]=1;                ans++;            }        return;    }       if (dep>n)  return;    dfs2(dep+1,s,ss);    dfs2(dep+1,s+a[dep],ss+pow(2,dep-1));    dfs2(dep+1,s-a[dep],ss+pow(2,dep-1));}int cmp(arr a,arr b){    return a.y<b.y;}int cmp2(arr a,arr b){    return a.y>b.y;}int main(){    scanf("%d",&n);    for (int i=1;i<=n;i++)        scanf("%d",&a[i]);      bobo=false;    dfs(1,0,0);    bobo=false;     dfs2(n/2+1,0,0);        sort(f+1,f+e+1,cmp);    sort(ff+1,ff+ee+1,cmp2);        int i=1,j=1;    while (i<=e && j<=ee)    {            if (f[i].y+ff[j].y>0 && j<=ee)  j++;            else if (f[i].y+ff[j].y<0 && i<=e)  i++;            if (f[i].y+ff[j].y==0)              {                int ii=i,jj=j;                while (1==1)                {                    if (!v[f[ii].x+ff[jj].x])                    {                        v[f[ii].x+ff[jj].x]=1;                        ans++;                    }                    if (ff[jj].y==ff[jj+1].y)   jj++;                    else if (f[ii].y==f[ii+1].y)                        {                            ii++;                            jj=j;                           }                    else break;                }                i=ii+1;                j=jj+1;            }    }       printf("%d",ans);}
原创粉丝点击