Description
Input
Output
Sample Input
3 10
1 2 10
Sample Output
5
Data Constraint
Hint
Solution
看到数据范围( n≤40 ),就不由自主地想到折半搜索。
于是把 n 先折半,每边
20 ,设两段的总花费分别为 x,y ,则显然满足:x+y≤m前半段 O(220) 枚举每个位置选不选(即顺便算出当前的 x ),
那么后半段的
y 就需要满足:y≤m−x那么我们可以将所有的 x 加入一个数组中,并从小到大排序。
在搜到一个
y 的时候,就在数组中二分查找,直接统计数量即可。总时间复杂度为 O(2N+N log N) 。
Code
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int mo=1e7+7;
int n,n1;
LL m,ans;
LL a[41],f[mo];
inline LL read()
{
LL X=0,w=1; char ch=0;
while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
return X*w;
}
inline void dfs1(int x,LL y)
{
if(y>m) return;
if(x>n1)
{
f[++f[0]]=y;
return;
}
dfs1(x+1,y+a[x]);
dfs1(x+1,y);
}
inline void dfs2(int x,LL y)
{
if(y>m) return;
if(x>n)
{
int l=1,r=f[0];
while(l<r)
{
int mid=(l+r)>>1;
if(f[mid]<=m-y) l=mid+1; else r=mid;
}
if(f[l]>m-y) l--;
ans+=l;
return;
}
dfs2(x+1,y+a[x]);
dfs2(x+1,y);
}
int main()
{
n=read(),m=read(),n1=n>>1;
for(int i=1;i<=n;i++) a[i]=read();
dfs1(1,0);
sort(f+1,f+1+f[0]);
dfs2(n1+1,0);
printf("%lld",ans);
return 0;
}