#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
 
using namespace std;
 
class Btree{
        public:
                int num;
                Btree *left;
                Btree *right;
 
                Btree():num(-1), left(NULL), right(NULL){};
                void insert(int x);
};
 
void Btree::insert(int x){
        if(num == -1)
                num = x;
        else if(x > num){
                if(right == NULL)
                        right = new Btree();
                right->insert(x);
        }
 
        else if(x <= num){
                if(left == NULL)
                        left = new Btree();
                left->insert(x);
        }
}
 
//cardsのうちK - num以上K - 1以下の和をもつ部分集合Sが作れるか//
//をDPで判定する関数//
bool search_set(vector<int> cards, int K, int num){
        //cardsが空なら無理//
        if(cards.empty())
                return false;
 
        //exist[i][j]はcardsのi枚目まで使って合計jとなる部分集合を作れるかどうか//
        bool exist[cards.size()][K] = {{0}};
 
        int i, j;
        //初期化//
        for(i = 1; i < K; i++){
                if(cards[0] == i)
                        exist[0][i] = true;
                else
                        exist[0][i] = false;
        }
 
        //条件を満たす集合が見つかったかのフラグ//
        bool find = false;
 
        //サイズが1の場合はループしなくてよい//
        if(cards.size() == 1){
                for(int k = K - num; k < K; k++){
                        if(exist[0][k] == true){
                                find = true;
                                break;
                        }
                }
 
                return find;
        }
 
        //それ以外はDPmatrixを埋めていく//
        //exist[i][j](K - num <= j <= K - 1)がtrueになるまでループ//
        for(unsigned int i = 1; i < cards.size(); i++){
                //K - num <= j <= K - 1がtrueになったかどうかのフラグ//
                bool ok = false;
                for(j = 1; j < K; j++){
                        if(exist[i - 1][j] == true){
                                exist[i][j] = true;
                                if(j + cards[i] < K)
                                        exist[i][j + cards[i]] = true;
                        }
                        if(cards[i] == j)
                                exist[i][j] = true;
 
                        if(j >= K - num && j <= K - 1 && exist[i][j] == true){
                                ok = true;
                                break;
                        }
                }
 
                //okがtrueなら見つかったので終了//
               if(ok){
                        find = true;
                        break;
                }
        }
 
        return find;
 
}
 
 
int main(){
        //カードの枚数N, 目標とする和K//
        int N, K;
 
        cin >> N >> K;
 
        //改行文字が入らないように1文字飛ばす//
        cin.ignore();
        //N個のカードうち、Kより小さい数字をもつものが格納されたvector cards//
        string str;
        vector<int> cards;
        int cnum;
        if(N > 1){
                for(int i = 0; i < N - 1; i++){
                        getline(cin, str, ' ');
                        cnum = stoi(str);
                        if(cnum < K)
                                cards.push_back(cnum);
                }
        }
        getline(cin, str);
        cnum = stoi(str);
        if(cnum < K)
                cards.push_back(stoi(str));
 
        //Kより小さいカードがないならすべて必要//
        if(cards.empty())
                cout << 0 << endl;
 
        else{
                //カードの和sumをとる//
                int sum = 0;
                for(unsigned int i = 0; i < cards.size(); i++)
                        sum += cards[i];
 
                //もしsumがKより小さいならKより小さいカードはすべて不要//
                if(sum < K)
                        cout << cards.size() << endl;
 
                //sumがKに等しいならすべて必要//
                else if(sum == K)
                        cout << 0 << endl;
 
                //それ以外は二分探索で必要か判断//
                else{
                        unsigned int i;
                        //2分探索木に数字をぶち込む//
                        Btree *parent = NULL;
                        parent = new Btree();
                        for(i = 0; i < cards.size(); i++)
                                parent->insert(cards[i]);
 
                        //カードaの数字Naとすると、S < K && S + Na >= Kなる集合が見つかれば//
                        //aは必要で、なければ不必要//
                        //大きい方から見て初めて不要なカードが出た時点で//
                        //それ以下の数のカードはすべて不要//
                        vector<int> n_cards;
                        //最後の数とそれが必要かどうか//
                        int last_num;
                        bool last_find;
                        while(parent != NULL){
                                //n_cardsにcardsをコピー//
                                copy(cards.begin(), cards.end(), back_inserter(n_cards));
                                //集合からparent->numを消去//
                                auto itr = find(n_cards.begin(), n_cards.end(), parent->num);
                                n_cards.erase(itr);
                                //search_setはcardsのうちK - cards[i] <= S <= K - 1//
                                //を満たす部分集合Sが存在するか確かめる関数//
                                //見つかればそれより大きい数は必要なので下界を調べに左へ//
                                //見つからなければ下界を調べに右へ//
                                last_num = parent->num;
                                if(search_set(n_cards, K, parent->num)){
                                        last_find = true;
                                        parent = parent->left;
                                }
                                else{
                                        last_find = false;
                                        parent = parent->right;
                                }
                                n_cards.clear();
                        }
                        //cardsをソート//
                        sort(cards.begin(), cards.end());
                        //最後の数が必要ならばそれより小さい数はすべて不必要//
                        if(last_find){
                                for(i = 0; i < cards.size(); i++){
                                        if(cards[i] == last_num)
                                                break;
                                }
                                cout << i << endl;
                        }
                        //最後の数が不必要ならそれ以下の数はすべて不必要//
                        else{
                                for(i = cards.size() - 1; i >= 0; i--){
                                        if(cards[i] == last_num)
                                                break;
                                }
                                cout << i + 1 << endl;
                        }
                }
        }
 
        return 0;
}
 

Measured memory_bytes: 24832