• 删数方案数(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 }
  • 相关阅读:
    vs2017 离线安装。
    c# begin & end.
    vc++ 下的WaitForSingleObject
    c# 工厂模式 ,委托 ,事件。
    微信分享 andriod studio
    mac osx 10.9 ftp server端口
    win32 调用多媒体函数PlaySound()
    [汇编语言]-第九章 在屏幕中间分别显示绿底红色,白底蓝色字符串"welcome to masm!"
    [汇编语言]-第九章 jcxz,loop指令,转移位移的意义
    补码
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7358055.html
Copyright © 2020-2023  润新知