传送门
解析:
这道题主要是折半的思想,搜索倒没有那么重要。
考虑直接搜索枚举选或不选
2
40
2^{40}
240是不现实的,
那直接把数列分成两半,搜索两个
2
20
2^{20}
220,这个复杂度是可以接受的,然后把两个拼起来就行了。
拼的过程可以考虑用哈希表来实现,也可以一前一后双指针扫一遍。
代码:
#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
#define int ll
cs int N=(1<<20)+6;
int A[42],n,key;
inline void solve(int l,int r,vector<int> &q){
int len=r-l+1;
for(int re sta=0;sta<(1<<len);++sta){
int tmp=0;
for(int re i=0;i<len;++i){
if(sta&(1<<i)){
tmp+=A[l+i];
}
}
q.push_back(tmp);
}
}
tr1::unordered_map<ll,ll> cnt;
vector<int> ql,qr;
signed main(){
scanf("%lld%lld",&n,&key);
for(int re i=1;i<=n;++i)scanf("%lld",&A[i]);
int mid=(1+n)>>1;
solve(1,mid,ql);
solve(mid+1,n,qr);
ll ans=0;
for(int re i=0;i<ql.size();++i)++cnt[ql[i]];
for(int re i=0;i<qr.size();++i)ans+=cnt[key-qr[i]];
cout<<ans;
return 0;
}