有n個物品,m塊錢,給定每一個物品的價格,求買物品的方案數。
sol:php
meet in the middleios
太感人了 我剛打完板子今天就看見一道題數組
具體來講 咱們分開 暴力枚舉前20個物品放不放 後20個物品放不放 將答案記錄到數組a和數組b中(爆搜)ide
複雜度$O(2^{20}*2)$spa
固然 如今答案確定不對 咱們枚舉a中每個元素 假設其爲x 在b中二分m-x 看看貢獻是多少debug
貢獻就是b的下標。而後ans+=b的下標便可。3d
複雜度$O(2^{20}log2^{20}+2^{20}*2+2^{20}log2^{20})$unix
//Meet In The Middle /*In Search Of Life*/ #include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<iomanip> #include<stack> #include<map> #include<set> #include<cmath> #define debug(x) cerr<<#x<<"="<<x<<endl #define INF 0x7f7f7f7f #define llINF 0x7fffffffffffll using namespace std; typedef pair<int,int> pii; typedef long long ll; inline int init() { int now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } inline long long llinit() { long long now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } ll a[1005]; ll res[3000005]; int n;ll m; #ifdef unix #define LLD "%lld" #else #define LLD "%I64d" #endif ll nex[3000005]; int pren=n/2; ll pans=0; ll ans=0; int pcnt=0,ncnt=0; int bSearch(int l,int r,ll x) { int pos=-1; int mid=((l+r)>>1); while(l<=r) { mid=((l+r)>>1); if(res[mid]>x) { r=mid-1; } else { l=mid+1; pos=mid; } } return pos; } void predfs(int now,ll V) { if(V>m)return; if(now==pren+1) { res[++pcnt]=V; return; } predfs(now+1,V+a[now]); predfs(now+1,V); return; } void nextdfs(int now,ll V) { if(V>m)return; if(now==n+1) { nex[++ncnt]=V; return; } nextdfs(now+1,V+a[now]); nextdfs(now+1,V); return; } void MeetInTheMiddle() { for(int i=1;i<=ncnt;i++) { ans+=bSearch(1,pcnt,m-nex[i]); } return; } int main() { n=init();m=llinit(); for(int i=1;i<=n;i++) { a[i]=llinit(); } pren=n/2; predfs(1,0); nextdfs((n/2)+1,0); sort(res+1,res+pcnt+1); MeetInTheMiddle(); printf(LLD,ans); return 0; }