#include using namespace std; #define rep(i, x, limit) for (long long i = (long long)x; i < (long long)limit; i++) #define REP(i, x, limit) for (long long i = (long long)x; i <= (long long)limit; i++) #define all(x) x.begin(), x.end() #define rall(x) x.rbegin(), x.rend() #define el '\n' #define spa " " #define inp(x) for(auto &i:x)cin>>i using ll = long long; using ull = unsigned long long; using vl = vector; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while(t--){ int n,s; cin >> n >> s; vector A(n); inp(A); // Sより大きいものは絶対使わない vector B; for(auto a:A){ if(a<=s) B.push_back(a); } sort(all(B)); // 全部選べるならそれが最大 ll sum=0; for(auto a:B) sum+=a; if(sum<=s){ cout< small,large; for(auto a:B){ if(2*a<=s) small.push_back(a); else large.push_back(a); } // dp[x] = smallだけで和xを作れる int W=s/64+1; vector dp(W); dp[0]=1ULL; // dp |= dp << shift auto shift_or = [&](int shift){ int ws=shift/64; int bs=shift%64; for(int i=W-1;i>=0;i--){ ull add=0; if(i-ws>=0){ add |= dp[i-ws]<=0){ add |= dp[i-ws-1]>>(64-bs); } dp[i]|=add; } }; // smallを同じ値ごとにまとめる for(int i=0;i<(int)small.size();){ int j=i; while(j<(int)small.size() && small[j]==small[i]){ j++; } int cnt=j-i; int k=1; while(cnt>0){ int take=min(k,cnt); ll shift=1LL*small[i]*take; if(shift<=s){ shift_or(shift); } cnt-=take; k*=2; } i=j; } auto can = [&](int x)->bool{ return (dp[x/64]>>(x%64))&1ULL; }; // largeを使わない場合 int j=s; while(j>=0 && !can(j)){ j--; } int ans=j; // largeは最大1個しか使えない // largeはBから作ったので既に昇順 for(auto a:large){ j=min(j,s-a); while(j>=0 && !can(j)){ j--; } if(j>=0){ ans=max(ans,a+j); } } cout<