bzoj4800 [Ceoi2015]Ice Hockey World Championship

66 篇文章 0 订阅

Description


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

n<=40,m<=10^18
(想怎么买就怎么买,当然不买也算一种)

Solution


其实我一开始不是很懂题意。。感觉这类的题目做一次就够了吧?

显然可行的暴力是dfs,时间复杂度不能承受就分成两半暴力然后二分查找
注意开LL的问题(只有我没开LL吧?

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)

typedef long long LL;
const int N=55;

LL a[N],v[N],m,ans;
int n;

void dfs1(int dep,LL sum) {
    if (sum>m) return ;
    if (dep==n/2+1) {
        v[++v[0]]=sum;
        return ;
    }
    dfs1(dep+1,sum+a[dep]);
    dfs1(dep+1,sum);
}

int find(LL x) {
    int ret;
    int l=1,r=v[0];
    while (l<=r) {
        int mid=(l+r)>>1;
        if (v[mid]<=x) ret=mid,l=mid+1;
        else r=mid-1;
    }
    return ret;
}

void dfs2(int dep,LL sum) {
    if (sum>m) return ;
    if (dep==n+1) {
        if (m-sum<v[1]) return ;
        ans+=find(m-sum);
        return ;
    }
    dfs2(dep+1,sum+a[dep]);
    dfs2(dep+1,sum);
}

int main(void) {
    scanf("%d%lld",&n,&m);
    rep(i,1,n) scanf("%lld",&a[i]);
    dfs1(1,0);
    std:: sort(v+1,v+v[0]+1);
    dfs2(n/2+1,0);
    printf("%lld\n", ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值