>Link
SSLOJ
>Description
1
≤
n
≤
50000
,
1
≤
k
≤
200000
,
1
≤
A
i
≤
1
0
9
1≤n≤50000, 1≤k≤200000,1≤Ai≤10^9
1≤n≤50000,1≤k≤200000,1≤Ai≤109
>解题思路
这道题竟然 二分+爆搜+剪枝 就能过
二分答案,爆搜来找和比
k
k
k 小的集合有多少个,加一些常规的剪枝
但是这样是60分,还有一个重要的剪枝就是把集合
A
A
A 从大到小排序,然后再爆搜,这样就可以跑得飞快,因为减少了很多不必要的搜索
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 50010
#define LL long long
using namespace std;
int n, k;
LL a[N], cnt, cntt, ans;
LL read ()
{
LL ret = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9')
{
ret = ret * (LL)10 + c - '0';
c = getchar();
}
return ret;
}
void dfs (int now, LL sum, LL w)
{
if (sum > w) return;
if (cnt >= k) return;
if (now == 0)
{
if (sum < w && sum != 0) cnt++;
if (sum == w) cntt++;
return;
}
dfs (now - 1, sum, w);
dfs (now - 1, sum + a[now], w);
}
int main()
{
// freopen ("16.in", "r", stdin);
n = read(), k = read();
LL l = 1, r = 0, mid;
for (int i = 1; i <= n; i++)
{
a[i] = read();
r += a[i];
}
sort (a + 1, a + 1 + n);
while (l <= r)
{
mid = (l + r) / 2;
cnt = 0;
cntt = 0;
dfs (n, 0, mid);
if (cnt < k && cnt + cntt >= k)
{
ans = mid;
break;
}
if (cnt >= k) r = mid - 1;
else l = mid + 1;
}
printf ("%lld", ans);
return 0;
}