#include typedef long long ll; typedef unsigned long long ull; #define FOR(i,a,b) for(int (i)=(a);i<(b);i++) #define REP(i,n) FOR(i,0,n) #define RANGE(vec) (vec).begin(),(vec).end() using namespace std; class CatalogueShopping { public: void solve(void) { int N; ll S; cin>>N>>S; vector P(N); REP(i, N) cin>>P[i]; // ∑P[i] = S なる I をみつければよい // i in I // // S が大きすぎるので DP は無理 // N が小さいので 2^N 全探索試すか? // 2^31 = 2147483648 > 10^7*200 なので無理 // 前半・後半列挙でやる vector> S1; int m = N; if (m > 16) m = 16; // O(2^17*m*log(N)) for (int b = 0; b < (1< S2((1<<(N-m)), 0); // O(2^17*N) for (int b = 0; b < (1<<(N-m)); ++b) { FOR(i,1,N-m+1) if (b & (1<<(N-m-i))) S2[b] += P[i+m-1]; } // 二分探索 // O(2^(N-m)*16) vector combs; REP(b2, 1<<(N-m)) { ll s2 = S2[b2]; if (s2 == S) { combs.push_back(b2); continue; } auto it1 = lower_bound(RANGE(S1), make_pair(S-s2, -1)); auto it2 = upper_bound(RANGE(S1), make_pair(S-s2, (1<<30))); if (it1 == S1.end() || it1->first != S-s2) continue; while (it1 != it2) { int b1; ll s1; tie(s1,b1) = *it1; combs.push_back(b1<<(N-m) | b2); ++it1; } } sort(RANGE(combs), greater()); for (auto b : combs) { string ans; FOR(i,1,N+1) if (b & (1<<(N-i))) ans+=to_string(i)+" "; cout<solve(); delete obj; return 0; } #endif