给出一个长度 (nleq 35) 的序列,求他的子集和的第 (k) 小
把前 n/2 的子集和放到一个数组里 后 n/2 的放到另一个数组里,然后问题转化为了求各取一个数和的第 (k) 小
可以二分第 (k) 小的数是多少
namespace QvvQ {
vll t1, t2;
int n, a[50];
ll k;
void dfs(int pos, int r, ll sum, vll &s) {
if (pos > r) return void(s.pb(sum));
dfs(pos + 1, r, sum + a[pos], s), dfs(pos + 1, r, sum, s);
}
void init() {
}
bool check(ll X) {//leq X 的数对的数量是否<k
ll cnt = 0;
for (int p1 = 0, p2 = t2.size() - 1; p1 != t1.size(); ++p1) {
while (p2 > 0 && t1[p1] + t2[p2] > X) --p2;
if (t1[p1] + t2[p2] <= X) cnt += p2 + 1;
if (cnt >= k) return 0;
}
return 1;
}
void solve() {
n = in, k = in;
lo1(i, n) in, a[i];
dfs(1, n >> 1, 0, t1), dfs(n / 2 + 1, n, 0, t2);
sort(all(t1)), sort(all(t2));
ll l = 1, r = t1.back() + t2.back();
while (l <= r) {
if (check(mid)) l = mid + 1;
else r = mid - 1;
}
out, l;//l-1+1 l-1是最后一个合法(<k)的
}
}
int main() {
#ifdef QvvQ
// freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
Dbg = 1;
#endif
int T = 1;
while (T--) QvvQ::init(), QvvQ::solve();
#ifdef QvvQ
fprintf(stderr, "
time:%.5fms", clock() * 1000.0 / CLOCKS_PER_SEC);
#endif
return 0;
}