// Author: Sahil Yasar
// Tested here:
// https://w...content-available-to-author-only...j.com/problems/LKS/ [0-1 Knapsack v-1]
// https://a...content-available-to-author-only...r.jp/contests/dp/tasks/dp_e [0-1 Knapsack v-2]
// https://l...content-available-to-author-only...u.vn/problem/knapsack3 [0-1 Knapsack v-3]
// https://c...content-available-to-author-only...s.fi/problemset/task/1634 [Unbounded Knapsack]
#include <iostream>
#include <cstring>
#include <numeric>
#include <vector>
#include <algorithm>
using namespace std;
#define endl '\n'
// Solution for small knapsack capacity
long long knapsack1(int w[], int v[], int& c, int& n){
long long ans[c+1];
memset(ans, 0, sizeof(ans));
for (int i = 0; i < n; ++i)
// for (int j = w[i]; j <= c; ++j) // Unbounded Knapsack
for (int j = c; j >= w[i]; --j) // 0-1 Knapsack
ans[j] = max(ans[j], ans[j-w[i]] + v[i]);
return ans[c];
}
// Solution for small sum of value
long long knapsack2(int w[], int v[], int& c, int& n){
int sum = accumulate(v, v+n, 0);
long long ans[sum+1];
memset(ans, 0x3f, sizeof(ans));
ans[0] = 0;
for (int i = 0; i < n; ++i)
for (int j = sum; j >= v[i]; --j) // 0-1 Knapsack
ans[j] = min(ans[j], ans[j-v[i]] + w[i]);
for (int i = sum; i >= 0; --i)
if (ans[i] <= c)
return i;
return 0;
}
struct node{
long long value, weight;
int mask;
node(int m, long long v = 0, long long w = 0)
: mask(m), value(v), weight(w) {}
};
void solve(int w[], int v[], long long c, int n, vector<node>& S){
int lim = 1<<n;
for (int mask = 0; mask < lim; ++mask){
long long weight = 0, value = 0;
for (int i = 0; i < n; ++i)
if ((mask>>i)&1){
weight += w[i];
value += v[i];
if (weight > c) break;
}
if (weight <= c)
S.push_back(node(mask, value, weight));
}
}
// Solution for small number of element
long long knapsack3(int w[], int v[], long long& c, int& n){
int m = n/2;
int wl[m], vl[m], wr[n-m], vr[n-m];
for (int i = 0; i < m; ++i)
wl[i] = w[i], vl[i] = v[i];
for (int i = m; i < n; ++i)
wr[i-m] = w[i], vr[i-m] = v[i];
vector<node> Sl, Sr;
solve(wl, vl, c, m, Sl);
solve(wr, vr, c, n-m, Sr);
sort(Sr.begin(), Sr.end(), [](node& a, node& b){
return (a.weight != b.weight)? a.weight < b.weight: a.value < b.value;
});
long long maxval[Sr.size()];
int maxmask[Sr.size()];
maxval[0] = Sr[0].value;
maxmask[0] = Sr[0].mask;
for (int i = 1; i < Sr.size(); ++i){
maxval[i] = (maxval[i-1] < Sr[i].value)? Sr[i].value: maxval[i-1];
maxmask[i] = (maxval[i-1] < Sr[i].value)?Sr[i].mask : maxmask[i-1];
}
long long res = 0, mask = 0;
for (node& x: Sl){
int l = 0, r = int(Sr.size())-1, mid;
while(l+1 < r){
mid = (l+r)/2;
if (x.weight + Sr[mid].weight <= c)
l = mid;
else
r = mid;
}
long long temp = maxval[l] + x.value;
if (res < temp){
res = temp;
mask = x.mask | (maxmask[l] << m);
}
}
return mask;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin.exceptions(cin.failbit);
long long n, c, i;
cin>>n>>c;
int w[n], v[n];
for (i = 0; i < n; ++i)
cin>>w[i]>>v[i];
long long mask = knapsack3(w, v, c, *(new int(n)));
cout<<__builtin_popcount(mask)<<endl;
for (i = 0; i < n; ++i)
if ((mask>>i)&1)
cout<<i+1<<" ";
cout<<endl;
return 0;
}
Ly8gQXV0aG9yOiBTYWhpbCBZYXNhcgovLyBUZXN0ZWQgaGVyZToKLy8gaHR0cHM6Ly93Li4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5qLmNvbS9wcm9ibGVtcy9MS1MvIFswLTEgS25hcHNhY2sgdi0xXQovLyBodHRwczovL2EuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLnIuanAvY29udGVzdHMvZHAvdGFza3MvZHBfZSBbMC0xIEtuYXBzYWNrIHYtMl0KLy8gaHR0cHM6Ly9sLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi51LnZuL3Byb2JsZW0va25hcHNhY2szIFswLTEgS25hcHNhY2sgdi0zXQovLyBodHRwczovL2MuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLnMuZmkvcHJvYmxlbXNldC90YXNrLzE2MzQgW1VuYm91bmRlZCBLbmFwc2Fja10KCiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGNzdHJpbmc+CiNpbmNsdWRlIDxudW1lcmljPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8YWxnb3JpdGhtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwojZGVmaW5lIGVuZGwgJ1xuJwoKLy8gU29sdXRpb24gZm9yIHNtYWxsIGtuYXBzYWNrIGNhcGFjaXR5CmxvbmcgbG9uZyBrbmFwc2FjazEoaW50IHdbXSwgaW50IHZbXSwgaW50JiBjLCBpbnQmIG4pewogICAgbG9uZyBsb25nIGFuc1tjKzFdOwogICAgbWVtc2V0KGFucywgMCwgc2l6ZW9mKGFucykpOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyArK2kpCiAgICAgICAgLy8gZm9yIChpbnQgaiA9IHdbaV07IGogPD0gYzsgKytqKSAvLyBVbmJvdW5kZWQgS25hcHNhY2sKICAgICAgICBmb3IgKGludCBqID0gYzsgaiA+PSB3W2ldOyAtLWopIC8vIDAtMSBLbmFwc2FjawogICAgICAgICAgICBhbnNbal0gPSBtYXgoYW5zW2pdLCBhbnNbai13W2ldXSArIHZbaV0pOwogICAgcmV0dXJuIGFuc1tjXTsKfQoKLy8gU29sdXRpb24gZm9yIHNtYWxsIHN1bSBvZiB2YWx1ZQpsb25nIGxvbmcga25hcHNhY2syKGludCB3W10sIGludCB2W10sIGludCYgYywgaW50JiBuKXsKICAgIGludCBzdW0gPSBhY2N1bXVsYXRlKHYsIHYrbiwgMCk7CiAgICBsb25nIGxvbmcgYW5zW3N1bSsxXTsKICAgIG1lbXNldChhbnMsIDB4M2YsIHNpemVvZihhbnMpKTsKICAgIGFuc1swXSA9IDA7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG47ICsraSkKICAgICAgICBmb3IgKGludCBqID0gc3VtOyBqID49IHZbaV07IC0taikgLy8gMC0xIEtuYXBzYWNrCiAgICAgICAgICAgIGFuc1tqXSA9IG1pbihhbnNbal0sIGFuc1tqLXZbaV1dICsgd1tpXSk7CiAgICBmb3IgKGludCBpID0gc3VtOyBpID49IDA7IC0taSkKICAgICAgICBpZiAoYW5zW2ldIDw9IGMpCiAgICAgICAgICAgIHJldHVybiBpOwogICAgcmV0dXJuIDA7Cn0KCnN0cnVjdCBub2RlewogICAgbG9uZyBsb25nIHZhbHVlLCB3ZWlnaHQ7CiAgICBpbnQgbWFzazsKICAgIG5vZGUoaW50IG0sIGxvbmcgbG9uZyB2ID0gMCwgbG9uZyBsb25nIHcgPSAwKQogICAgOiBtYXNrKG0pLCB2YWx1ZSh2KSwgd2VpZ2h0KHcpIHt9Cn07Cgp2b2lkIHNvbHZlKGludCB3W10sIGludCB2W10sIGxvbmcgbG9uZyBjLCBpbnQgbiwgdmVjdG9yPG5vZGU+JiBTKXsKICAgIGludCBsaW0gPSAxPDxuOwogICAgZm9yIChpbnQgbWFzayA9IDA7IG1hc2sgPCBsaW07ICsrbWFzayl7CiAgICAgICAgbG9uZyBsb25nIHdlaWdodCA9IDAsIHZhbHVlID0gMDsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IG47ICsraSkKICAgICAgICAgICAgaWYgKChtYXNrPj5pKSYxKXsKICAgICAgICAgICAgICAgIHdlaWdodCArPSB3W2ldOwogICAgICAgICAgICAgICAgdmFsdWUgKz0gdltpXTsKICAgICAgICAgICAgICAgIGlmICh3ZWlnaHQgPiBjKSBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIGlmICh3ZWlnaHQgPD0gYykKICAgICAgICAgICAgUy5wdXNoX2JhY2sobm9kZShtYXNrLCB2YWx1ZSwgd2VpZ2h0KSk7CiAgICB9Cn0KCi8vIFNvbHV0aW9uIGZvciBzbWFsbCBudW1iZXIgb2YgZWxlbWVudApsb25nIGxvbmcga25hcHNhY2szKGludCB3W10sIGludCB2W10sIGxvbmcgbG9uZyYgYywgaW50JiBuKXsKICAgIGludCBtID0gbi8yOwogICAgaW50IHdsW21dLCB2bFttXSwgd3Jbbi1tXSwgdnJbbi1tXTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbTsgKytpKQogICAgICAgIHdsW2ldID0gd1tpXSwgdmxbaV0gPSB2W2ldOwogICAgZm9yIChpbnQgaSA9IG07IGkgPCBuOyArK2kpCiAgICAgICAgd3JbaS1tXSA9IHdbaV0sIHZyW2ktbV0gPSB2W2ldOwoKICAgIHZlY3Rvcjxub2RlPiBTbCwgU3I7CiAgICBzb2x2ZSh3bCwgdmwsIGMsIG0sIFNsKTsKICAgIHNvbHZlKHdyLCB2ciwgYywgbi1tLCBTcik7CiAgICBzb3J0KFNyLmJlZ2luKCksIFNyLmVuZCgpLCBbXShub2RlJiBhLCBub2RlJiBiKXsKICAgICAgICByZXR1cm4gKGEud2VpZ2h0ICE9IGIud2VpZ2h0KT8gYS53ZWlnaHQgPCBiLndlaWdodDogYS52YWx1ZSA8IGIudmFsdWU7CiAgICB9KTsKICAgIGxvbmcgbG9uZyBtYXh2YWxbU3Iuc2l6ZSgpXTsKICAgIGludCBtYXhtYXNrW1NyLnNpemUoKV07CiAgICBtYXh2YWxbMF0gPSBTclswXS52YWx1ZTsKICAgIG1heG1hc2tbMF0gPSBTclswXS5tYXNrOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPCBTci5zaXplKCk7ICsraSl7CiAgICAgICAgbWF4dmFsW2ldID0gKG1heHZhbFtpLTFdIDwgU3JbaV0udmFsdWUpPyBTcltpXS52YWx1ZTogbWF4dmFsW2ktMV07CiAgICAgICAgbWF4bWFza1tpXSA9IChtYXh2YWxbaS0xXSA8IFNyW2ldLnZhbHVlKT9TcltpXS5tYXNrIDogbWF4bWFza1tpLTFdOwogICAgfQoKICAgIGxvbmcgbG9uZyByZXMgPSAwLCBtYXNrID0gMDsKICAgIGZvciAobm9kZSYgeDogU2wpewogICAgICAgIGludCBsID0gMCwgciA9IGludChTci5zaXplKCkpLTEsIG1pZDsKICAgICAgICB3aGlsZShsKzEgPCByKXsKICAgICAgICAgICAgbWlkID0gKGwrcikvMjsKICAgICAgICAgICAgaWYgKHgud2VpZ2h0ICsgU3JbbWlkXS53ZWlnaHQgPD0gYykKICAgICAgICAgICAgICAgIGwgPSBtaWQ7CiAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgIHIgPSBtaWQ7CiAgICAgICAgfQogICAgICAgIGxvbmcgbG9uZyB0ZW1wID0gbWF4dmFsW2xdICsgeC52YWx1ZTsKICAgICAgICBpZiAocmVzIDwgdGVtcCl7CiAgICAgICAgICByZXMgPSB0ZW1wOwogICAgICAgICAgbWFzayA9IHgubWFzayB8IChtYXhtYXNrW2xdIDw8IG0pOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBtYXNrOwp9CgppbnQgbWFpbigpewogICAgaW9zX2Jhc2U6OnN5bmNfd2l0aF9zdGRpbyhmYWxzZSk7CiAgICBjaW4udGllKE5VTEwpOwogICAgY2luLmV4Y2VwdGlvbnMoY2luLmZhaWxiaXQpOwoKICAgIGxvbmcgbG9uZyBuLCBjLCBpOwogICAgY2luPj5uPj5jOwogICAgaW50IHdbbl0sIHZbbl07CiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKQogICAgICBjaW4+PndbaV0+PnZbaV07CgogICAgbG9uZyBsb25nIG1hc2sgPSBrbmFwc2FjazModywgdiwgYywgKihuZXcgaW50KG4pKSk7CiAgICBjb3V0PDxfX2J1aWx0aW5fcG9wY291bnQobWFzayk8PGVuZGw7CiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKQogICAgICBpZiAoKG1hc2s+PmkpJjEpCiAgICAgICAgY291dDw8aSsxPDwiICI7CiAgICBjb3V0PDxlbmRsOwoKICAgIHJldHVybiAwOwp9Cg==