luogu4799 [CEOI2015 Day2]世界冰球锦标赛

luogu4799 [CEOI2015 Day2]世界冰球锦标赛

P4799 [CEOI2015 Day2]世界冰球锦标赛
傻题。。。
但是考试因为这个算法挂了两次
折半搜索,一次搜一半,然后考虑合并起来就好了,这么简单的折半搜索..
如果特别难合并的话,直接使用爆搜+剪枝在幸运的情况下是可以过掉这道题的.

/*header*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#define rep(i , x, p) for(int i = x;i <= p;++ i)
#define sep(i , x, p) for(int i = x;i >= p;-- i)
#define gc getchar()
#define pc putchar
#define ll long long
#define mk make_pair
#define fi first
#define se second
using std::min;
using std::max;
using std::swap;

inline ll gi() {
    ll x = 0,f = 1;char c = gc;
    while(c < '0' || c > '9') {if(c == '-')f = -1;c = gc;}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = gc;}return x * f;
}

void print(int x) {
    if(x < 0) pc('-') , x = -x;
    if(x >= 10) print(x / 10);
    pc(x % 10 + '0');
}

const int maxN = 40 + 7;

ll a[maxN] , ans, sum[1048580] , cnt , m;
int n;

void dfs(int tot , ll tsum) {
    if(tsum > m) return;
    if(tot == 0) {
        sum[++ cnt] = tsum;
        return;
    }
    dfs(tot - 1 , tsum + a[tot]);
    dfs(tot - 1 , tsum);
}

void dfs2(int tot , ll tsum) {
    if(tsum > m) return;
    if(tot == n + 1) {
    if(m - tsum >= sum[cnt]) ans += cnt;
    else ans += std::upper_bound(sum + 1 , sum + cnt + 1 , m - tsum) - sum - 1;
        return;
    }
    dfs2(tot + 1 , tsum + a[tot]);
    dfs2(tot + 1 , tsum);
}

int main() {
    scanf("%d",&n);
    m = gi();
    rep(i , 1, n) a[i] = gi();
    dfs(n  / 2 , 0LL);
    std::sort(sum + 1 , sum + cnt + 1);
    dfs2( n / 2 + 1, 0LL);
    printf("%lld",ans);
    return 0;
}
/*
5 1000
100 1500 500 500 1000
*/

猜你喜欢

转载自www.cnblogs.com/gzygzy/p/10314407.html