链接
http://www.lydsy.com/JudgeOnline/problem.php?id=4800
题解
一开始自己
YY
了爆搜+一大堆剪枝,但是发现仍然能造出卡掉我的数据,于是放弃了看了题解。
题解说是
meeting in the middle
感觉好神奇。
你就先爆搜前
20
个物品把所哟的方案扔到一个数组里,后
20
个同理,最后两个表排个序,然后枚举第一数组里的一个数,在第二个数组里二分下。
代码
//dfs + meeting in the middle
#include <cstdio>
#include <algorithm>
#define maxn 2000000
#define ll long long
using namespace std;
ll list1[maxn], list2[maxn], N, cost[maxn], M, E, ans;
void dfs(ll pos, ll sum, ll *list)
{
if(sum>M)return;
if(pos>E){list[++*list]=sum;return;}
dfs(pos+1,sum,list);
dfs(pos+1,sum+cost[pos],list);
}
void input()
{
int i;
scanf("%lld%lld",&N,&M);
for(i=1;i<=N;i++)scanf("%lld",cost+i);
}
void work()
{
int l, r, mid, i;
E=N/2;
dfs(1,0,list1);
E=N;
dfs(N/2+1,0,list2);
sort(list1+1,list1+*list1+1);
sort(list2+1,list2+*list2+1);
for(i=1;i<=*list1;i++)
{
if(list2[1]+list1[i]>M)break;
for(l=1,r=*list2;l<r;)
{
mid=l+r+1>>1;
if(list1[i]+list2[mid]<=M)l=mid; else r=mid-1;
}
ans+=l;
}
}
int main()
{
input();
work();
printf("%lld",ans);
return 0;
}