1. 程式人生 > >2018.11.01【NOIP訓練】某種密碼(折半搜尋)

2018.11.01【NOIP訓練】某種密碼(折半搜尋)

傳送門

解析:

這道題主要是折半的思想,搜尋倒沒有那麼重要。

考慮直接搜尋列舉選或不選2402^{40}是不現實的, 那直接把數列分成兩半,搜尋兩個2202^{20},這個複雜度是可以接受的,然後把兩個拼起來就行了。

拼的過程可以考慮用雜湊表來實現,也可以一前一後雙指標掃一遍。

程式碼:

#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; }