P4799世界冰球锦标赛洛谷

完整AC代码,注释很详细
 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, m, nums[45];
ll ans;//答案个数
ll p[1 << 21];//可能性 这是一半的所有可能情况,爆搜极限是2 ^ 40,一半就是2 ^ 20,多给点空间
ll k;//一半n / 2
ll cnt;//记录p有多少个
void ldfs(ll index, ll s) {
    if (index == k) {
            //到一半的头了,记录当前数
        p[cnt++] = s;
        return;
     }
    //这个门票就两种情况,选还不是不选
    ldfs(index + 1, s);//不选
    if (s + nums[index] <= m) ldfs(index + 1, s + nums[index]);//选的情况得if判断,不能超过限定的金额
}
void rdfs(ll index,ll s) {
    if (index == n) {
           //又到一半的头了
        //s + a <= m 这就是当前符合情况的门票数 那这个a <= m - s 此时用upper找这个,同时,所以,前面ldfs搜完得对p数组排序的
        auto it = upper_bound(p, p + cnt, m - s) - p;
        ans += it;//拿到结果
        return;
     }
    //还是选或者不选
    rdfs(index + 1, s);//不选
    if (s + nums[index] <= m) rdfs(index + 1, s + nums[index]);//和ldfs一样的思路
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
    cin >> n >> m;
    //下面预处理的是用点技巧,稍微剪剪枝
    int j = 0;//数组中真正数字的个数
    for (int i = 0; i < n; ++i) {
        cin >> nums[j];//注意,是j不是i
        if (nums[j] <= m)++j;//只有当前输入的这个数小于等于m才记入数组,不然压根不放进去,不过这里也不是完全意义上的不放进去
        //因为比如最后一个大于了,j不变,但是for循环已经结束,这样还是放进去了,但是,注意,后面n的修改还是依据j,它虽然放进去了
        //但是也是压根不会遍历到的!!!
    }
    n = j;//变换n
    sort(nums, nums + n, greater<ll>());//从大到小,这样也能加快点速度
    k = n / 2;//拿到真正数组个数的一半
    //以上就是预处理的全部过程
    ldfs(0, 0);
    //拿到p数组得排序,不然后序的upper没法用
    sort(p, p + cnt);
    rdfs(k, 0);
    cout << ans << endl;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值