subsets
T1就是个对半搜索裸题……考场上直接A了……没啥好说的……
#include <cstdio>
using namespace std;
const int pps=1e6+7,maxtot=6e4;
int n;
int ans,fake;
bool bo[1<<21];
int val[25],belong[25];
int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
}
struct Hash {
int tot,cnt;
int head[pps];
int val[maxtot],nxt[maxtot];
int now[maxtot],mzf[maxtot*10],pre[maxtot*10];
void link(int a,int b) {
pre[++cnt]=now[a];
now[a]=cnt;mzf[cnt]=b;
}
void find(int u,int oxy) {
for(int p=now[u];p;p=pre[p])
if(mzf[p]==oxy)return;
link(u,oxy);
}
void add(int v,int oxy) {
int pos=(v%pps+pps)%pps;
for(int p=head[pos];p;p=nxt[p])
if(val[p]==v) {find(p,oxy);return;}
++tot;val[tot]=v;nxt[tot]=head[pos];head[pos]=tot;
link(tot,oxy);
}
void query(int v,int oxy) {
int pos=(v%pps+pps)%pps;
for(int p=head[pos];p;p=nxt[p])
if(val[p]==v) {
for(int u=now[p];u;u=pre[u])
bo[mzf[u]|oxy]=1;
return;
}
}
}H;
void prepare() {
int res=0,oxy=0;
for(int i=1;i<=n/2;i++) {
if(belong[i])oxy|=1<<(i-1);
if(belong[i]==1)res+=val[i];
else if(belong[i]==2)res-=val[i];
}
H.add(res,oxy);
}
void query() {
int res=0,oxy=0;
for(int i=n/2+1;i<=n;i++) {
if(belong[i])oxy|=1<<(i-1);
if(belong[i]==1)res-=val[i];
else if(belong[i]==2)res+=val[i];
}
H.query(res,oxy);
}
void dfs_front(int id) {
if(id==n/2) {prepare();return;}
for(int i=0;i<3;i++) {
belong[id+1]=i;
dfs_front(id+1);
}
}
void dfs_behind(int id) {
if(id==n) {query();return;}
for(int i=0;i<3;i++) {
belong[id+1]=i;
dfs_behind(id+1);
}
}
int main() {
freopen("subsets.in","r",stdin);
freopen("subsets.out","w",stdout);
n=read();
for(int i=1;i<=n;i++) {
val[i]=read();
if(!val[i])fake++;
}
dfs_front(0);dfs_behind(n/2);
for(int s=1;s<1<<n;s++)
if(bo[s])ans++;
printf("%d\n",ans-fake);
return 0;
}