CodeEff/ECCO huggingface dataset:
# Original solution
N,K = list(map(int,input().split()))
a = list(map(int,input().split()))
a.sort()
if a[0] >= K:
    print((0))
    exit()

a = [a[i] for i in range(N) if a[i]<K]
N = len(a)
ans = N
dp = [False]*K
dp[0] = True
Smax = 0
for i,a_ in reversed(list(enumerate(a))):
    if Smax + a_ >= K:
        ans = i
    updated = True
    for j in range(min(Smax,K-a_-1),-1,-1):
        if dp[j]:
            dp[j+a_]=True
            if updated:
                Smax = max(Smax,j+a_)
                updated = False

print(ans)

# Optimized solution
N,K = list(map(int,input().split()))
a = list(map(int,input().split()))

def f(N,K,a):
    a.sort()
    if a[0] >= K:
        print((0))
        exit()

    a = [a[i] for i in range(N) if a[i]<K]
    N = len(a)
    ans = N
    dp = [False]*K
    dp[0] = True
    Smax = 0
    for i,a_ in reversed(list(enumerate(a))):
        if Smax + a_ >= K:
            ans = i
        updated = True
        for j in range(min(Smax,K-a_-1),-1,-1):
            if dp[j]:
                dp[j+a_]=True
                if updated:
                    Smax = max(Smax,j+a_)
                    updated = False
    return ans

print((f(N,K,a)))
# Original solution
N,K=list(map(int,input().split()))
A=list(map(int,input().split()))
A.sort()
import bisect
idx=bisect.bisect_left(A,K)
ans=0
A=A[:idx]
N=idx
from collections import defaultdict
def search(i):
    dp=defaultdict(int)
    dp[0]=1
    ai=A[i]
    for j in range(N):
        dpc=dp.copy()
        if i==j:continue
        for k in list(dpc.keys()):
            if k+A[j]>=K or dpc[k]==0:
                continue
            if k+A[j]>=K-ai:
                return True
            dp[k+A[j]]=1
    return False
MinTrue=N
MaxFalse=-1
check=(1,2)
while MinTrue-MaxFalse>1:
    idx=N*check[0]//check[1]
    if search(idx):
        MinTrue=min(MinTrue,idx)
        check=(check[0]*2-1,check[1]*2)
    else:
        MaxFalse=max(MaxFalse,idx)
        check=(check[0]*2+1,check[1]*2)
print(MinTrue)

# Optimized solution
N,K=list(map(int,input().split()))
A=list(map(int,input().split()))
A.sort(reverse=True)
S=0
ans=0
for a in A:
    if S+a<K:
        S+=a
        ans+=1
    else:ans=0
print(ans)
# Original solution
n, k = list(map(int,input().split()))
A = list(map(int,input().split()))

A.sort()
# print(A)

le = -1
ri = len(A)
mid = (le + ri) // 2
while ri - le > 1:
    # print(le,ri,mid)
    DP = [0 for i in range(k)]
    DP[0] = 1
    for i in range(n):
        #print(DP)
        if i != mid:
            for p in range(k-1, A[i]-1, -1):
                DP[p] = int(DP[p-A[i]] or DP[p])
        # print(j)
    need = 0
    #print(DP)
    for p in range(max(0, k-A[mid]), k):
        if DP[p] == 1:
            need = 1
            break
    
    if need == 1:
        ri = mid
    else:
        le = mid
    mid = (le + ri) // 2

print((le + 1))

# Optimized solution
n, k = list(map(int,input().split()))
A = list(map(int,input().split()))

A.sort()
# print(A)
A_set = list(set(A))

A_set = [int(i) for i in A_set]
A_set.sort()

#print(A_set)

le = -1
ri = len(A_set)
mid = (le + ri) // 2

while ri - le > 1:
    need = 0
    # print(le,ri,mid)

    DP = [0 for i in range(k)]
    DP[0] = 1
    jogai = 0
    for i in range(n):
        #print(DP)
        if jogai == 0 and A[i] == A_set[mid]:
            jogai = 1
        else:
            for p in range(k-1, A[i]-1, -1):
                DP[p] = int(DP[p-A[i]] or DP[p])
            # print(j)
    
            #print(DP)
        for p in range(max(0, k-A_set[mid]), k):
            if DP[p] == 1:
                need = 1
                break
        if need == 1:
            break
    
    if need == 1:
        ri = mid
    else:
        le = mid
    mid = (le + ri) // 2


ans = 0

if le != -1:
    jougen = A_set[le]
    for i in range(n):
        if A[i] <= jougen:
            ans += 1

print(ans)
# Original solution
N,K = list(map(int,input().split()))
a = list(map(int,input().split()))

dp1 = [[False]*K for _ in range(N)]
dp2 = [[False]*K for _ in range(N)]
# dp[x][y] x枚目まで使った時にyに出来るか
# K-ai <= ai < K となる部分集合を探す
dp1[0][0] = True
if a[0] < K:
    dp1[0][a[0]] = True 
for i in range(1,N):
    for j in range(K):
        dp1[i][j] = dp1[i-1][j] or (j-a[i] >= 0 and dp1[i-1][j-a[i]])

dp2[0][0] = True
if a[N-1] < K:
    dp2[0][a[N-1]] = True
for i in range(1,N):
    for j in range(K):
        dp2[i][j] = dp2[i-1][j] or (j-a[N-i-1] >= 0 and dp2[i-1][j-a[N-i-1]])
count = 0
for i in range(N):
    if K-a[i] <= 0:
        count += 1
        continue
    for j in range(K-a[i],K):
        f = False
        if i == 0:
            if dp2[N-2][j]:
                count += 1
                break
            else:
                continue
        elif i == N-1:
            if dp1[N-2][j]:
                count += 1
                break
            else:
                continue
        for k in range(j+1):
            if dp1[i-1][k] and dp2[N-i-2][j-k]:
                count += 1
                f = True
                break
        if f:
            break
print((N-count))


# Optimized solution
N,K = list(map(int,input().split()))
a = sorted(map(int,input().split()))

count = N
s = 0
for i in range(N-1,-1,-1):
    if s + a[i] < K:
        s += a[i]
    else:
        count = min(i,count)
print(count)
# Original solution
N,K=list(map(int,input().split()))
A=list(map(int,input().split()))
A.sort()

l=N
for i in range(0,N):
    if A[i]>=K:
        l=i
        break
A=A[:l]
N=l
#A[num]が必要な数か判定
def condition(num):
    if N-1>num:
        test=A[:num]+A[num+1:]
    else:
        test=A[:num]
    if A[num]>=K:
        return True
    else:
        dp=[False for i in range(0,K)]
        for i in range(K-A[num],K):
            dp[i]=True

        for i in range(1,N):
            for j in range(0,K-test[i-1]):
                dp[j]=dp[j] or dp[j+test[i-1]]
        return dp[0]

#必要な数のうち最小のもの
if N==0:
    print((0))
elif N==1:
    if A[0]>=K:
        print((0))
    else:
        print((1))
else:
    start=0
    end=N-1
    while end-start>1:
        t=(end+start)//2
        if condition(t):
            end=t
        else:
            start=t

    if condition(start):
        print(start)
    elif condition(end):
        print(end)
    else:
        print(N)

# Optimized solution
N,K=list(map(int,input().split()))
A=list(map(int,input().split()))
A.sort()

l=N
for i in range(0,N):
    if A[i]>=K:
        l=i
        break
A=A[:l]
N=l
#A[num]が必要な数か判定
def condition(num):
    if N-1>num:
        test=A[:num]+A[num+1:]
    else:
        test=A[:num]
    if A[num]>=K:
        return True
    else:
        check=0
        for i in range(K-A[num],K):
            check+=pow(2,i)

        for i in range(1,N):
            check=check|(check>>test[i-1])

        return check%2==1
        

#必要な数のうち最小のもの
if N==0:
    print((0))
elif N==1:
    if A[0]>=K:
        print((0))
    else:
        print((1))
else:
    start=0
    end=N-1
    while end-start>1:
        t=(end+start)//2
        if condition(t):
            end=t
        else:
            start=t

    if condition(start):
        print(start)
    elif condition(end):
        print(end)
    else:
        print(N)
# Original solution
def I(): return int(eval(input()))
def MI(): return list(map(int, input().split()))
def LI(): return list(map(int, input().split()))

def main():
    N,K=MI()
    a=LI()#下位の連続するn枚が不要なはず
    a.sort(reverse = True)
    
    
    #i番目までを使ってjが作れるかどうか
    dp=[[False]*K for _ in range(N+1)]
    dp[0][0]=1
    for i in range(N):
        for j in range(K):
            if dp[i][j]==1:
                dp[i+1][j]=1
                jj=j+a[i]
                if jj<K:
                    dp[i+1][jj]=1
                    
                    
    #i番目以降を使ってjが作れるかどうか
    dp2=[[0]*K for _ in range(N+1)]
    dp2[-1][0]=True
    for i in range(N):
        for j in range(K):
            if dp2[-1-i][j]==True:
                dp2[-2-i][j]=True
                jj=j+a[-1-i]
                if jj<K:
                    dp2[-2-i][jj]=True
    
    #累積和チックに
    for i in range(N+1):
        for j in range(K-1):
            dp[i][j+1]+=dp[i][j]
                    
                    
    #x番目の数が必要かどうかの判定 
    #必要なものだけで構成された集合をもとに考えれば良いわけではない，不必要な分も考えなければならない             
    def ch(x):
        if a[x]>=K:
            return True
        else:
            #dp2でsを作り，dpで，K-s未満，K-a[x]-s以上のものが作れれば良い，
            #この範囲内で1が一つでもあれば良いので，累積和の差分が1以上ならok
            for s in range(K-a[x]):
                if dp2[x+1][s]==True:
                    if dp[x][K-s-1] - dp[x][K-a[x]-s-1]>=1:
                        return True
        return False
    
                        
    ng=N
    ok=-1
    while abs(ok-ng)>1:
        med=(ok+ng)//2
        
        if ch(med):
            ok=med
        else:
            ng=med
            
    print((N-(ok+1)))
    
    
   
    
            
    
    
    

main()


# Optimized solution
def I(): return int(eval(input()))
def MI(): return list(map(int, input().split()))
def LI(): return list(map(int, input().split()))

def main():
    N,K=MI()
    a=LI()#下位の連続するn枚が不要なはず
    a.sort()
                    
                    
    #x番目の数が必要かどうかの判定 
    #必要なものだけで構成された集合をもとに考えれば良いわけではない，不必要な分も考えなければならない             
    def ch(x):
        if a[x]>=K:
            return True
        else:
            #使い回す，i番目まででjが作れるか
            dp=[False]*K
            dp[0]=True
            for i in range(N):
                if i==x:
                    continue
                else:
                    for j in range(K-1,-1,-1):
                        jj=j-a[i]
                        if jj>=0:
                            if dp[jj]:
                                dp[j]=True
                    
                            
            #K未満K-a[x]以上が作れれば良い    
            for j in range(K-a[x],K):
                if  dp[j]:
                    return True
            return False
                
            
            
        return False
    
                        
    ng=-1
    ok=N
    while abs(ok-ng)>1:
        med=(ok+ng)//2
        
        if ch(med):
            ok=med
        else:
            ng=med
            
    print((ng+1))
    
    
   
    
            
    
    
    

main()
# Original solution
def main():
    def I(): return int(eval(input()))
    def MI(): return list(map(int, input().split()))
    def LI(): return list(map(int, input().split()))
    
    N,K=MI()
    a=LI()#下位の連続するn枚が不要なはず
    a.sort()
    for i in range(N):#K以上ならば必要
        if a[i]>=K:
            a=a[:i]
            break
    N=len(a)
                    
                    
    #x番目の数が必要かどうかの判定 
    #必要なものだけで構成された集合をもとに考えれば良いわけではない，不必要な分も考えなければならない             
    def ch(x):
        
        #使い回す，i番目まででjが作れるか
        dp=[0]*K
        dp[0]=1
        for i in range(N):
            if i==x:
                continue
            else:
                for j in range(K-1,a[i]-1,-1):
                    dp[j]|=dp[j-a[i]]
                
                        
        #K未満K-a[x]以上が作れれば良い    
        for j in range(K-a[x],K):
            if  dp[j]:
                return True
        return False
            
    
                        
    ng=-1
    ok=N
    while abs(ok-ng)>1:
        med=(ok+ng)//2
        
        if ch(med):
            ok=med
        else:
            ng=med
            
    print((ng+1))
    
    
 
    

main()


# Optimized solution
def I(): return int(eval(input()))
def MI(): return list(map(int, input().split()))
def LI(): return list(map(int, input().split()))

def main():

    
    N,K=MI()
    a=LI()#下位の連続するn枚が不要なはず
    a.sort()
    for i in range(N):#K以上ならば必要
        if a[i]>=K:
            a=a[:i]
            break
    N=len(a)
                    
                    
    #x番目の数が必要かどうかの判定 
    #必要なものだけで構成された集合をもとに考えれば良いわけではない，不必要な分も考えなければならない             
    def ch(x):
        
        #使い回す，i番目まででjが作れるか
        dp=[0]*K
        dp[0]=1
        for i in range(N):
            if i==x:
                continue
            else:
                for j in range(K-1,a[i]-1,-1):
                    dp[j]|=dp[j-a[i]]
                
                        
        #K未満K-a[x]以上が作れれば良い    
        for j in range(K-a[x],K):
            if  dp[j]:
                return True
        return False
            
    
                        
    ng=-1
    ok=N
    while abs(ok-ng)>1:
        med=(ok+ng)//2
        
        if ch(med):
            ok=med
        else:
            ng=med
            
    print((ng+1))
    
    
   
    
            
    
    
    

main()
# Original solution
def I(): return int(eval(input()))
def MI(): return list(map(int, input().split()))
def LI(): return list(map(int, input().split()))

def main():

    
    N,K=MI()
    a=LI()#下位の連続するn枚が不要なはず
    a.sort()
    for i in range(N):#K以上ならば必要
        if a[i]>=K:
            a=a[:i]
            break
    N=len(a)
                    
                    
    #x番目の数が必要かどうかの判定 
    #必要なものだけで構成された集合をもとに考えれば良いわけではない，不必要な分も考えなければならない             
    def ch(x):
        
        #使い回す，i番目まででjが作れるか
        dp=[0]*K
        dp[0]=1
        for i in range(N):
            if i==x:
                continue
            else:
                for j in range(K-1,a[i]-1,-1):
                    dp[j]|=dp[j-a[i]]
                
                        
        #K未満K-a[x]以上が作れれば良い    
        for j in range(K-a[x],K):
            if  dp[j]:
                return True
        return False
            
    
                        
    ng=-1
    ok=N
    while abs(ok-ng)>1:
        med=(ok+ng)//2
        
        if ch(med):
            ok=med
        else:
            ng=med
            
    print((ng+1))
    
    
   
    
            
    
    
    

main()


# Optimized solution
def I(): return int(eval(input()))
def MI(): return list(map(int, input().split()))
def LI(): return list(map(int, input().split()))

def main():

    
    N,K=MI()
    a=LI()#下位の連続するn枚が不要なはず
    a.sort(reverse=True)
    #大きい方から順に足していき，K未満の最大の和を作っておく．これに対して，足してK以上になるのならそれは必要．K未満なら端しておく．
    #最終的に必要なもののうち最も小さいものがわかるはず
    
    temp=0
    ans=N
    for i in range(N):
        if temp+a[i]<K:
            temp+=a[i]
        else:
            ans=min(ans,N-i-1)
            
    print(ans)
    
    


main()
# Original solution
N,K = list(map(int, input().split()))
A = [int(a) for a in input().split()]

A.sort()

def f(n): #aiが必要か不必要か判定
    if A[n] >= K:
        return True
    if n == 0:
        L = A[n+1:]
    elif n == N-1:
        L = A[:n]
    else:
        L = A[:n] + A[n+1:]
    
    dp0 = [0]*K
    dp0[0] = 1
    dp1 = [0]*K
    for i in range(N-1):
        for j in range(K):
            if i%2 == 0:
                if j < L[i]:
                    dp1[j] = dp0[j]
                    continue
                dp1[j] = dp0[j] | dp0[j-L[i]]
            else:
                if j < L[i]:
                    dp0[j] = dp1[j]
                    continue
                dp0[j] = dp1[j] | dp1[j-L[i]]
        
    res = False
    if N%2 == 0:
        for j in range(K-A[n], K):
            if dp1[j]:
                res = True
                break
    else:
        for j in range(K-A[n], K):
            if dp0[j]:
                res = True
                break
            
    return res

l = -1
r = N
while r-l > 1:
    m = (l+r)//2
    if f(m):
        r = m
    else:
        l = m
        
print(r)

# Optimized solution
N,K = list(map(int, input().split()))
A = [int(a) for a in input().split()]

A.sort()
for i in range(N):
    if A[i] >= K:
        A = A[:i]
        break

N = len(A)

def f(n): #aiが必要か不必要か判定
    dp = [0]*K
    dp[0] = 1
    for i in range(N):
        if i == n:
            continue
        for j in range(K-1, A[i]-1, -1):
            dp[j] |= dp[j-A[i]]
            
    res = False
    for j in range(K-A[n], K):
        if dp[j]:
            res = True
            break
    return res

l = -1
r = N
while r-l > 1:
    m = (l+r)//2
    if f(m):
        r = m
    else:
        l = m
        
print(r)
# Original solution
n,k=list(map(int,input().split()))
a=[int(i) for i in input().split()]
a.sort()

def check(d):#そいつが必要か
    global a,n,k
    dp=[0]*(k)#k-1まで
    if a[d]>=k:
        return True
    for i in range(n):
        if i!=d:
            dp_sub=[0]*(k)
            for j in range(k-1):
                if j==0 or dp[j]!=0:
                    if j+a[i]<k:
                        dp_sub[j+a[i]]=1
                    else:
                        break
            for j in range(k):
                if dp_sub[j]==1:
                    dp[j]=1
                    if j+a[d]>=k:
                        return True
    return False
l,r=0,n-1
while l+1<r:
    d=(l+r)//2
    if check(d):#必要か
        r=d
    else:
        l=d
if check(l):
    print(l)
else:
    if check(r):
        print(r)
    else:
        print((r+1))

# Optimized solution
N, K = list(map(int, input().split()))
a = list(map(int, input().split()))
 
a = sorted(a)
ans = N
t = 0

for i in range(N-1, -1, -1) :
    if t+a[i] < K :
        t += a[i]
    else :
        ans = min(ans, i)
 
print(ans)
# Original solution
import sys
input = lambda : sys.stdin.readline().rstrip()
sys.setrecursionlimit(max(1000, 10**9))
write = lambda x: sys.stdout.write(x+"\n")


n,k = list(map(int, input().split()))
a = list(map(int, input().split()))
a.sort()
def sub(ii):
    dp = 1
    for i in range(n):
        if i==ii:
            continue
        dp |= dp<<a[i]
#         for j in range(k-1, a[i]-1, -1):
#             dp[j] += dp[j-a[i]]
    val = max(i for i in range(k) if (dp>>i)&1)
    return val+a[ii]>=k
if sub(0):
    ans = 0
elif not sub(n-1):
    ans = n
else:
    l = 0
    r = n-1
    while l<r-1:
        m = (l+r)//2
        if sub(m):
            r = m
        else:
            l = m
    ans = l+1
print(ans)

# Optimized solution
import sys
input = lambda : sys.stdin.readline().rstrip()
sys.setrecursionlimit(max(1000, 10**9))
write = lambda x: sys.stdout.write(x+"\n")


n,k = list(map(int, input().split()))
a = list(map(int, input().split()))
a.sort()
def sub(ii):
    dp = 1
    mask = (1<<(k+1)) - 1
    for i in range(n):
        if i==ii:
            continue
        dp |= dp<<a[i]
        dp &= mask
#         for j in range(k-1, a[i]-1, -1):
#             dp[j] += dp[j-a[i]]
    val = max(i for i in range(k) if (dp>>i)&1)
    return val+a[ii]>=k
if sub(0):
    ans = 0
elif not sub(n-1):
    ans = n
else:
    l = 0
    r = n-1
    while l<r-1:
        m = (l+r)//2
        if sub(m):
            r = m
        else:
            l = m
    ans = l+1
print(ans)
# Original solution
import sys
input = lambda : sys.stdin.readline().rstrip()
sys.setrecursionlimit(max(1000, 10**9))
write = lambda x: sys.stdout.write(x+"\n")


n,k = list(map(int, input().split()))
a = list(map(int, input().split()))
a.sort()
mask = (1<<(k+1)) - 1
def sub(ii):
    dp = 1
    for i in range(n):
        if i==ii:
            continue
        dp |= (dp<<a[i]) & mask
#         for j in range(k-1, a[i]-1, -1):
#             dp[j] += dp[j-a[i]]
    val = max(i for i in range(k) if (dp>>i)&1)
    return val+a[ii]>=k
if sub(0):
    ans = 0
elif not sub(n-1):
    ans = n
else:
    l = 0
    r = n-1
    while l<r-1:
        m = (l+r)//2
        if sub(m):
            r = m
        else:
            l = m
    ans = l+1
print(ans)

# Optimized solution
import sys
input = lambda : sys.stdin.readline().rstrip()
sys.setrecursionlimit(max(1000, 10**9))
write = lambda x: sys.stdout.write(x+"\n")


n,k = list(map(int, input().split()))
a = list([min(int(x), k+1) for x in input().split()])
a.sort()
mask = (1<<(k+1)) - 1
def sub(ii):
    dp = 1
    for i in range(n):
        if i==ii:
            continue
        dp |= (dp<<a[i]) & mask
#         for j in range(k-1, a[i]-1, -1):
#             dp[j] += dp[j-a[i]]
    val = max(i for i in range(k) if (dp>>i)&1)
    return val+a[ii]>=k
if sub(0):
    ans = 0
elif not sub(n-1):
    ans = n
else:
    l = 0
    r = n-1
    while l<r-1:
        m = (l+r)//2
        if sub(m):
            r = m
        else:
            l = m
    ans = l+1
print(ans)
# Original solution
# -*- coding: utf-8 -*-

import sys
from collections import defaultdict
from bisect import bisect_left

def input(): return sys.stdin.readline().strip()
def list2d(a, b, c): return [[c] * b for i in range(a)]
def list3d(a, b, c, d): return [[[d] * c for j in range(b)] for i in range(a)]
def list4d(a, b, c, d, e): return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]
def ceil(x, y=1): return int(-(-x // y))
def INT(): return int(eval(input()))
def MAP(): return list(map(int, input().split()))
def LIST(N=None): return list(MAP()) if N is None else [INT() for i in range(N)]
def Yes(): print('Yes')
def No(): print('No')
def YES(): print('YES')
def NO(): print('NO')
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
MOD = 10 ** 9 + 7

N, K = MAP()
A = LIST()

# 部分和DPを変形させて、その値になるのに使われた値の集合を持っておく
dp = defaultdict(list)
dp[0].append(0)
for i in range(N):
    for j in range(K-1, -1, -1):
        if len(dp[j]):
            dp[j+A[i]] += dp[j]
            dp[j+A[i]].append(A[i])

# 和がK未満の集合はこの後のチェックで使わないので削る
dp = sorted(dp.items())
keys, lists = list(zip(*dp))
idx = bisect_left(keys, K)
keys = keys[idx:]
lists = lists[idx:]
sets = [set() for i in range(len(lists))]
for i, li in enumerate(lists):
    sets[i] = set(li)

ans = 0
for i in range(N):
    for k, s in zip(keys, sets):
        # A[i]減らしたらK未満になる状況で、一度でもA[i]が使われていれば必要
        if k-A[i] < K and A[i] in s:
            break
    else:
        # 該当するどの集合でも、一度も使われていなければ不要
        ans += 1
print(ans)


# Optimized solution
# -*- coding: utf-8 -*-

import sys

def input(): return sys.stdin.readline().strip()
def list2d(a, b, c): return [[c] * b for i in range(a)]
def list3d(a, b, c, d): return [[[d] * c for j in range(b)] for i in range(a)]
def list4d(a, b, c, d, e): return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]
def ceil(x, y=1): return int(-(-x // y))
def INT(): return int(eval(input()))
def MAP(): return list(map(int, input().split()))
def LIST(N=None): return list(MAP()) if N is None else [INT() for i in range(N)]
def Yes(): print('Yes')
def No(): print('No')
def YES(): print('YES')
def NO(): print('NO')
sys.setrecursionlimit(10 ** 9)
INF = float('inf')
MOD = 10 ** 9 + 7

def bisearch_min(mn, mx, func):
    """ 条件を満たす最小値を見つける二分探索 """

    ok = mx
    ng = mn
    while ng+1 < ok:
        mid = (ok+ng) // 2
        if func(mid):
            # 下を探しに行く
            ok = mid
        else:
            # 上を探しに行く
            ng = mid
    return ok

N, K = MAP()
A = LIST()

def check(omit):
    # 部分和DP
    dp = [0] * K
    dp[0] = 1
    for i in range(1, N+1):
        for j in range(K-1, -1, -1):
            if i-1 != omit and j-A[i-1] >= 0:
                dp[j] |= dp[j-A[i-1]]
    # 今回の値A[omit]を足してKに到達できるような部分和があれば、これは必要
    for j in range(max(0, K-A[omit]), K):
        if dp[j]:
            return True
    # なければ不要
    return False

A.sort()
print((bisearch_min(-1, N, check)))
# Original solution
import itertools
N,K = list(map(int,input().split()))
A = list(map(int,input().split()))
A.sort()
need = []
iranaiko = []
for a in A:
	if a >= K:
		need.append(a)
	elif a in need:
		need.append(a) 
	elif a in iranaiko:
		pass
	else:
		z = 0
		B = A[:]
		B.remove(a)
		fusoku = [K - i - 1 for i in range(a)]
		for bi,b in enumerate(B):
			if b >= K:
				break
		B = B[:bi + 1]
		for i in range(1,len(B) + 1):
			C = list(itertools.combinations(B,i))
			p = 0
			for c in C:
				if sum(c) in fusoku:
					need.append(a)
					z = 1
					break
				if sum(c) >= K:
					p = p + 1 
					if p == len(C):
						iranaiko.append(a)
						z = 1
						break
			if z == 1:
				break
		if z == 0:
			iranaiko.append(a)
print((N - len(need)))


# Optimized solution
import itertools
N,K = list(map(int,input().split()))
A = list(map(int,input().split()))
A.sort()
need = []
iranaiko = []
for a in A:
	if a >= K:
		need.append(a)
	elif a in need:
		need.append(a) 
	elif a in iranaiko:
		pass
	else:
		z = 0
		B = A[:]
		B.remove(a)
		fusoku = [K - i - 1 for i in range(a)]
		for bi,b in enumerate(B):
			if b >= K:
				break
		B = B[:bi + 1]
		B.reverse()
		C = [0]
		for b in B:
			D = []
			for c in C:
				if b + c < K:
					if b + c in fusoku:
						z = 1
						need.append(a)
						break
					D.append(b + c)
				
			D.append(0)
			C = D[:]
			if z == 1:
				break
			
			

print((N - len(need)))