2018.11.01【NOIP訓練】某種密碼(折半搜尋)
阿新 • • 發佈:2018-12-18
傳送門
解析:
這道題主要是折半的思想,搜尋倒沒有那麼重要。
考慮直接搜尋列舉選或不選是不現實的, 那直接把數列分成兩半,搜尋兩個,這個複雜度是可以接受的,然後把兩個拼起來就行了。
拼的過程可以考慮用雜湊表來實現,也可以一前一後雙指標掃一遍。
程式碼:
#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;
}