[BZOJ]4800: [Ceoi2015]Ice Hockey World Championship dfs+二分

来源:互联网 发布:linux 复制几个字符 编辑:程序博客网 时间:2024/06/06 06:32

Description

有n个物品,m块钱,给定每个物品的价格,求买物品的方案数。

题解:

不错的题目,应该看了代码就知道怎么做了吧。

代码:

#include<bits/stdc++.h>using namespace std;#define pa pair<int,int>#define LL long longconst int Maxn=45;const int inf=2147483647;LL read(){    LL x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}    return x*f;}int n,lenA=0,lenB=0,lim;LL m,a[Maxn],b[Maxn],A[1100000],B[1100000];void dfs1(int x,LL t){    if(t>m)return;    if(x==lim+1){A[++lenA]=t;return;}    dfs1(x+1,t);dfs1(x+1,t+a[x]);}void dfs2(int x,LL t){    if(t>m)return;    if(x==lim+1){B[++lenB]=t;return;}    dfs2(x+1,t);dfs2(x+1,t+a[x]);}int work(LL x){    int l=1,r=lenA;    while(l<=r)    {        int mid=l+r>>1;        if(A[mid]+x<=m)l=mid+1;        else r=mid-1;    }return l-1;}int main(){    n=read();m=read();    if(n<=20)    {        for(int i=1;i<=n;i++)a[i]=read();        lim=n;dfs1(1,0);        printf("%d",lenA);    }    else    {        for(int i=1;i<=n;i++)a[i]=read();        lim=20;dfs1(1,0);sort(A+1,A+1+lenA);        lim=n;dfs2(21,0);        LL ans=0;        for(int i=1;i<=lenB;i++)        {            if(B[i]+A[lenA]<=m)ans+=lenA;            else ans+=(LL)(work(B[i]));        }printf("%lld",ans);    }}
阅读全文
1 0
原创粉丝点击