#include <bits/stdc++.h>
using namespace std;

#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define MIN(a) *min_element(all(a))
#define MAX(a) *max_element(all(a))
#define SUM(a) accumulate(all(a), 0LL)
#define REP(i, n) for(int (i)=0; (i)<(n); (i)++)
#define RREP(i, n) for(int (i)=(n)-1; (i)>=0; (i)--)
#define FOR(i, m, n) for(int (i)=(m); (i)<(n); i++)
#define FORR(i, m, n) for(int (i)=(n)-1; (i)>=(m); i--)
#define debug(x) cerr << #x << " = " << x << endl
//#define int long long

typedef long long ll;
//ll const MOD = 998244353;
ll const MOD = 1e9+7;
int const inf = 1e9;
ll const INF = 1e18;

inline void ios_(){cin.tie(0); ios::sync_with_stdio(false);}
template<typename T> int size(const T& a){return (int)a.size();}
template<typename T> T Div(T a, T b){return (a + b - 1) / b;}
template<typename T> bool chmin(T& a, const T& b){if(a > b){a = b; return true;} return false;}
template<typename T> bool chmax(T& a, const T& b){if(a < b){a = b; return true;} return false;}

template<typename T> struct SegmentTree {
    int N;                  //要素数
    T idt;                  //単位元
    vector<T> node;         //ノード (1-indexed, node[0]=idt)
    function<T(T,T)> fn;    //二項演算

    //要素を引数のベクトルから受け取る
    SegmentTree(const vector<T>& v, T id, function<T(T,T)> f) : idt(id), fn(f) {
        N = 1 << calcRank(v.size());
        node.resize(2*N);
        
        for(int i=0; i<2*N; i++) {
            if(i >= N && i < N + v.size()) {    //最下層のノードに要素を格納
                node[i] = v[i - N];
            }else{
                node[i] = idt;
            }
        }

        build();
    }

    int calcRank(int n) {
        int res = 0;
        n--;
        while(n > 0) {
            res++;
            n /= 2;
        }
        return res;
    }

    void build() {
        for (int i=N-1; i>0; i--) {
            node[i] = fn(node[2*i], node[2*i + 1]);
        }
    }

    void update(int k, T value) {    //値の更新
        k += N;    //要素番号->ノード番号
        node[k] = value;

        while(k > 1) {
            k /= 2;
            node[k] = fn(node[2*k], node[2*k + 1]); //上に向かって値を更新する
        }
    }

    T query(int a, int b) {  //半開区間 [a,b) に対するクエリ
        return query(a, b, 1, 0, N);
    }

    T query(int a, int b, int k, int l, int r) { //計算用の内部関数
        if(r <= a || b <= l) {   //[a,b) と [l,r) が交差しない場合
            return idt;
        }
        if(a <= l && r <= b) {   //[l,r) が [a,b) に含まれる場合
            return node[k];
        }

        T vl = query(a, b, 2*k, l, (l+r)/2);    //左右に分けて再帰
        T vr = query(a, b, 2*k+1, (l+r)/2, r);

        return fn(vl, vr);
    }
};

template<typename T> struct LazySegmentTree : SegmentTree<T> {
    vector<T> lazy;
    function<T(T,T)> gn;
    function<T(T,int)> p;

    LazySegmentTree(const vector<T>& v,
                    T id,
                    function<T(T,T)> f,
                    function<T(T,T)> g,
                    function<T(T,int)> p) : SegmentTree<T>(v, id, f), gn(g), p(p) {
        lazy.resize(2*this->N, id);
    }

    void eval(int k, int len) { // 遅延配列のデータを適用
        if(lazy[k] == this->idt) return;
        if(k < this->N) {
            lazy[2*k] = gn(lazy[2*k], lazy[k]);
            lazy[2*k+1] = gn(lazy[2*k+1], lazy[k]); 
        }
        this->node[k] = gn(this->node[k], p(lazy[k], len));
        lazy[k] = this->idt;
    }

    T update(int a, int b, T value, int k, int l, int r) {
        eval(k, r - l);

        if(r <= a || b <= l) return this->node[k];
        if(a <= l && r <= b) {
            lazy[k] = gn(lazy[k], value);
            return gn(this->node[k], p(lazy[k], r - l));
        }

        T vl = update(a, b, value, k*2, l, (l+r)/2);
        T vr = update(a, b, value, 2*k+1, (l+r)/2, r);
        return this->node[k] = this->fn(vl, vr);
    }

    void update(int a, int b, T value) {    // 区間 [a,b) を更新
        update(a, b, value, 1, 0, this->N);
    }

    T query(int a, int b, int k, int l, int r) {
        eval(k, r - l);

        if(r <= a || b <= l) return this->idt;
        if(a <= l && r <= b) return this->node[k];

        T vl = query(a, b, 2*k, l, (l+r)/2);
        T vr = query(a, b, 2*k+1, (l+r)/2, r);

        return this->fn(vl, vr);
    }

    T query(int a, int b) {  //半開区間 [a,b) に対するクエリ
        return query(a, b, 1, 0, this->N);
    }
};


signed main(){
    int n, k;
    cin >> n >> k;

    vector<int> v(n);
    REP(i, n){
        cin >> v[i];
        chmin(v[i], k);
    }

    vector<vector<bool>> dp(n+2, vector<bool>(k)), rdp(n+2, vector<bool>(k, 0));
    dp[0][0] = true;
    rdp[n+1][0] = true;

    REP(i, n){
        REP(j, k){
            dp[i+1][j] = dp[i+1][j] | dp[i][j];
            if(j + v[i] < k){
                dp[i+1][j + v[i]] = dp[i+1][j + v[i]] | dp[i][j];
            }
        }
    }

    FORR(i, 1, n+1){
        REP(j, k){
            rdp[i][j] = rdp[i][j] | rdp[i+1][j];
            if(j + v[i-1] < k){
                rdp[i][j + v[i-1]] = rdp[i][j + v[i-1]] | rdp[i+1][j];
            }
        }
    }

    int ans = 0;
    REP(i, n){
        if(v[i] >= k) continue;
        int m = k - v[i];
        bool ok = false;

        SegmentTree<bool> tree(
            rdp[i+2],
            false,
            [](bool a, bool b){return a | b;}
        );

        REP(j, k){
            if(dp[i][j] == 0) continue;
            if(j >= m && dp[i][j] > 0){
                ok = true;
            }
            int ma = k - 1 - j, mi = max(0, m - j);
            if(tree.query(mi, ma + 1)){
                ok = true;
                break;
            }
        }
        if(!ok){
            ans++;
        }
    }

    cout << ans << endl;

    return 0;
}


Measured memory_bytes: 8832