【JZOJ5264】化学
Description
Input
Output
Sample Input
3 10
1 2 10
Sample Output
5
Hint
题解:
这个题目通过30%部分分的提示,我们可以猜出这个题目的正解就是折半搜索(然而我还是没做出来,毕竟是第一次写这种题吧!),我们考虑,先搜出前一半的,将所有方案的话费都记下来(存在f数组中),sort一遍,然后搜下一半,搜到最后的时候,对于每种方案(记后一半的花费为w),显然只要w+f[i]<=m就是合法方案,所以对于每个方案我们可以二分出最大的合法前一半方案的位置,直接统计答案就可以了.
代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define ll long long using namespace std; ll coss[50],f[1<<22]; ll n,m,tot,nn,anss=0; void dfs1(int now,int co){ if(co>m) return; if(now==nn+1){ f[++tot]=co; return; } dfs1(now+1,co+coss[now]); dfs1(now+1,co); } void dfs2(int now,int co){ if(co>m) return; if(now==n+1){ int l=1,r=tot,mid,ans=0; while(l<=r){ mid=(l+r)/2; if(f[mid]+co<=m) ans=mid,l=mid+1; else r=mid-1; } anss+=ans; return; } dfs2(now+1,co+coss[now]); dfs2(now+1,co); } int main() { scanf("%lld%lld",&n,&m);nn=n/2; for(int i=1;i<=n;i++) scanf("%lld",&coss[i]); dfs1(1,0); sort(f+1,f+tot+1); dfs2(nn+1,0); printf("%lld",anss); return 0; }