1. 程式人生 > >刪數方案數(regex)

刪數方案數(regex)

部分 沒有 urn 不能 n) 輸入 hash scan include

[題目描述]

給出一個正整數序列 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 }

刪數方案數(regex)