CodeEff/ECCO huggingface dataset:
# Original solution
import sys
stdin = sys.stdin

def li(): return [int(x) for x in stdin.readline().split()]
def li_(): return [int(x)-1 for x in stdin.readline().split()]
def lf(): return [float(x) for x in stdin.readline().split()]
def ls(): return stdin.readline().split()
def ns(): return stdin.readline().rstrip()
def lc(): return list(ns())
def ni(): return int(ns())
def nf(): return float(ns())

from collections import Counter

n,k = li()
a = li()

a_ltk = [ai for ai in a if ai < k]
a_ltk.sort(reverse=True)
need = {ai:False for ai in a_ltk}

# 貪欲に足していく
for i in range(len(a_ltk)):
    cur = 0
    stack = []
    for j in range(i,len(a_ltk)):
        cur += a_ltk[j]
        stack.append(a_ltk[j])
        if cur >= k:
            for key in stack:
                need[key] = True
            stack.pop()
            cur -= a_ltk[j]

                
cnt = Counter(a_ltk)
ans = 0

for k,v in list(need.items()):
    if not v:
        ans += cnt[k]
        
print(ans)

# Optimized solution
import sys
stdin = sys.stdin

def li(): return [int(x) for x in stdin.readline().split()]
def li_(): return [int(x)-1 for x in stdin.readline().split()]
def lf(): return [float(x) for x in stdin.readline().split()]
def ls(): return stdin.readline().split()
def ns(): return stdin.readline().rstrip()
def lc(): return list(ns())
def ni(): return int(ns())
def nf(): return float(ns())

from collections import Counter

n,k = li()
a = li()

a_ltk = [ai for ai in a if ai < k]
a_ltk.sort(reverse=True)
need = {ai:False for ai in a_ltk}

# 貪欲に足していく
for i in range(len(a_ltk)):
    cur = 0
    stack = []
    for j in range(i,len(a_ltk)):
        cur += a_ltk[j]
        stack.append(a_ltk[j])
        if cur >= k:
            for key in set(stack):
                if need[key]:
                    continue
                else:
                    need[key] = True
            stack.pop()
            cur -= a_ltk[j]

                
cnt = Counter(a_ltk)
ans = 0

for k,v in list(need.items()):
    if not v:
        ans += cnt[k]
        
print(ans)
# Original solution
#import numpy as np
MAX_INT = int(10e10)

N,K = list(map(int,input().split()))
cards = list(map(int,input().split()))
cards.sort()
cards += [MAX_INT]
#print(cards)
left = -1
right = N
while right - left > 1:
  middle = (left+right)//2
  #print(left,right,middle,cards[middle])
  dp = [[0]*K for i in range(N+2)]
  for i in range(N+1):
    for j in range(K):
      if i == middle:
        dp[i+1][j] = dp[i][j]
      else:
        if cards[i] <= j:
          dp[i+1][j] = max(dp[i][j],dp[i][j-cards[i]]+cards[i])
        else:
          dp[i+1][j] = dp[i][j]
  if dp[N][K-1] + cards[middle] >= K:
    right = middle
    #print(True)
  else:
    left = middle
    #print(False)
print(right)

# Optimized solution
#import numpy as np
MAX_INT = int(10e10)

N,K = list(map(int,input().split()))
cards = list(map(int,input().split()))
cards.sort()
cards += [MAX_INT]
#print(cards)
dp = [[0]*K for i in range(N+2)]
left = -1
right = N
while right - left > 1:
  middle = (left+right)//2
  #print(left,right,middle,cards[middle])
  for i in range(N+1):
    for j in range(K):
      if i == middle:
        dp[i+1][j] = dp[i][j]
      else:
        if cards[i] <= j:
          dp[i+1][j] = max(dp[i][j],dp[i][j-cards[i]]+cards[i])
        else:
          dp[i+1][j] = dp[i][j]
  #print(dp)
  if dp[N][K-1] + cards[middle] >= K:
    right = middle
    #print(True)
  else:
    left = middle
    #print(False)
print(right)
# Original solution
import sys
N,K=list(map(int, input().split()))
a=list(map(int, input().split()))
sum=0
for i in range(0,N):
  sum+=a[i]
if sum<K:#全部不必要
  print(N)
  sys.exit()
if sum==K:#全部必要
  print((0))
  sys.exit()
a.sort()
a.reverse()

#K未満の最大の数字のラベルはどこ？
l=N
for i in range(N-1,-1,-1):
  if a[i]<K:
    l=i
  else:
    break

if l==N:
  print((0))
  sys.exit()

count=N
#lまでの要素が必要か不要かチェック(使いまわし可能)
sum=0
for j in range(l,N):
  if sum+a[j]<K:
    sum+=a[j]
for i in range(0,l):  
  if sum+a[i]>=K:#必要ってことだ
    count-=1
#lからの要素は自分のことを抜かないといけないことに注意
for i in range(l,N):
  sum=0
  b=a[:]
  C=b.pop(i)
  for j in range(l-1,N-1):
    if sum+b[j]<K:
      sum+=b[j]
  if sum+C>=K:#必要ってことだ
    count-=1
print(count)

# Optimized solution
import sys
N,K=list(map(int, input().split()))
a=list(map(int, input().split()))
sum=0
for i in range(0,N):
  sum+=a[i]
if sum<K:#全部不必要
  print(N)
  sys.exit()
if sum==K:#全部必要
  print((0))
  sys.exit()
a.sort()
a.reverse()
 
#K未満の最大の数字のラベルはどこ？
l=N
for i in range(N-1,-1,-1):
  if a[i]<K:
    l=i
  else:
    break
 
if l==N:
  print((0))
  sys.exit()
 
count=N
#lまでの要素が必要か不要かチェック(使いまわし可能)
sum=0
l_list=[]
for j in range(l,N):
  if sum+a[j]<K:
    sum+=a[j]
    l_list.append(a[j])
for i in range(0,l):  
  if sum+a[i]>=K:#必要ってことだ
    count-=1
#lからの要素は自分のことを抜かないといけないことに注意
for i in range(l,N):
  if a[i] in l_list:
    sum=0
    b=a[:]
    C=b.pop(i)
    for j in range(l-1,N-1):
      if sum+b[j]<K:
        sum+=b[j]
    if sum+C>=K:#必要ってことだ
      count-=1
  else:
    count-=1
print(count)
# Original solution
import sys
input = sys.stdin.readline


def main():
    N, K = list(map(int, input().split()))
    A = list(map(int, input().split()))

    dp1 = [set() for _ in range(N)]
    dp1[0].add(0)
    for n in range(N-1):
        for pm in dp1[n]:
            dp1[n+1].add(pm)
            if pm + A[n] < K:
                dp1[n+1].add(pm+A[n])

    dp2 = [set() for _ in range(N)]
    dp2[N-1].add(0)
    for n in reversed(list(range(1, N))):
        for pm in dp2[n]:
            dp2[n-1].add(pm)
            if pm+A[n] < K:
                dp2[n-1].add(pm+A[n])

    ans = 0
    for n, a in enumerate(A):
        b = K - a
        if b <= 0: continue
        need = False
        B1 = sorted(dp1[n])
        B2 = sorted(dp2[n], reverse=True)
        i2 = 0
        for b1 in B1:
            while B2[i2] + b1 >= K:
                i2 += 1
                if i2 == len(B2): break
            if i2 == len(B2): break
            if b1+B2[i2] < b:
                continue
            else:
                need = True
                break
        if not need: ans += 1
    print(ans)


if __name__ == "__main__":
    main()

# Optimized solution
import sys
input = sys.stdin.readline

def main():
    N, K = list(map(int, input().split()))
    A = list(map(int, input().split()))

    dp1 = [[0]*K for _ in range(N)]
    dp1[0][0] = 1
    for n in range(N-1):
        for k in range(K):
            if k < A[n]:
                dp1[n+1][k] = dp1[n][k]
            else:
                dp1[n+1][k] = dp1[n][k] | dp1[n][k-A[n]]

    dp2 = [[0]*K for _ in range(N)]
    dp2[N-1][0] = 1
    for n in reversed(list(range(1, N))):
        for k in range(K):
            if k < A[n]:
                dp2[n-1][k] = dp2[n][k]
            else:
                dp2[n-1][k] = dp2[n][k] | dp2[n][k-A[n]]

    ans = 0
    for n, a in enumerate(A):
        b = K - a
        if b <= 0: continue
        need = False
        k2 = K-1
        for k1 in range(K):
            if not dp1[n][k1]: continue
            while not dp2[n][k2] or k1+k2 >= K:
                k2 -= 1
            if k1+k2 < b:
                continue
            else:
                need = True
                break
        if not need: ans += 1
    print(ans)

if __name__ == "__main__":
    main()
# Original solution
# -*- coding:utf-8 -*-
from itertools import combinations
n,k = list(map(int,input().split()))
a = list(map(int, input().split()))
a=sorted(a)
o=0
discard = []
hold = []
checked = []
# 再帰関数をつくる

if sum(a) < k:
    o = n
else:
    for i in range(n,-1,-1):
        b = list(combinations(a, i+1))

        # 組み合わせ全通り
        for c in b:
            # それぞれの組み合わせ検証
            s = sum(c)
            if s >= k:
                # 良い集合だけを検証、なければそれ以下の集合は検証しない
                c = reversed(c)
                for d in c:
                    if (s-d) >=k:
                        discard.append(d)
                        discard=list(set(discard))
                    else:
                        # 未満になれば、その数値は必要、それ以後の取り出しは無意味なのでbreak
                        hold.append(d)
                        hold=list(set(hold))
                    checked.append(d)
            else:
                pass
    ans = list(set(discard)-set(hold))
    o = len(ans)
print(o)


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

n,k = list(map(int,input().split()))
a = list(map(int, input().split()))
a = list(reversed(sorted(a)))
nec = 0
for i in range(n):
    s = 0
    for j in range(i,n):
        s += a[j]
        if s >= k:
            nec = max(nec,j+1)
            s -= a[j]

print((n-nec))
# Original solution
def solve(n):
    global N, K
    dp = [[0] * (K + 1) for _ in range(N + 1)]
    dp[0][0] = 1
    for i in range(N):
        a = 0 if i == n else A[i]
        for j in range(max(0, K - a + 1)):
            here = dp[i][j]
            dp[i + 1][j + a] |= here
            dp[i + 1][j] |= here
    rst = any(dp[N][k] for k in range(max(0, K - A[n]), K))
    return rst


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


# [ok, ng) - Maximum
# (ng, ok] - Minimum
# ok が 最終的な答え
ok = N
ng = -1
while abs(ok - ng) > 1:
    mid = (ok + ng) // 2
    n = mid
    dp = [[0] * (K + 1) for _ in range(N + 1)]
    dp[0][0] = 1
    for i in range(N):
        a = 0 if i == n else A[i]
        for j in range(K + 1):
            here = dp[i][j]
            dp[i + 1][min(K, j + a)] |= here
            dp[i + 1][j] |= here
    rst = any(dp[N][k] for k in range(max(0, K - A[n]), K))
    if rst:
        ok = mid
    else:
        ng = mid
print(ok)


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


# [ok, ng) - Maximum
# (ng, ok] - Minimum
# ok が 最終的な答え
ok = N
ng = -1
while abs(ok - ng) > 1:
    mid = (ok + ng) // 2
    n = mid
    dp = [0] * (K + 1)
    dp[0] = 1
    for i in range(N):
        a = 0 if i == n else A[i]
        for j in range(K, -1, -1):
            dp[min(K, j + a)] |= dp[j]
    rst = any(dp[k] for k in range(max(0, K - A[n]), K))
    if rst:
        ok = mid
    else:
        ng = mid
print(ok)
# Original solution
def main():
    N, K = list(map(int, input().split()))
    A = list(map(int, input().split()))
    A.sort()


    # [ok, ng) - Maximum
    # (ng, ok] - Minimum
    # ok が 最終的な答え
    ok = N
    ng = -1
    while abs(ok - ng) > 1:
        mid = (ok + ng) // 2
        n = mid
        dp = [0] * (K + 1)
        dp[0] = 1
        for i in range(N):
            a = A[i]
            if i == n or a >= K:
                continue
            for j in range(K, -1, -1):
                dp[min(K, j + a)] |= dp[j]
        rst = any(dp[k] for k in range(max(0, K - A[n]), K))
        if rst:
            ok = mid
        else:
            ng = mid
    print(ok)


main()


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


    # [ok, ng) - Maximum
    # (ng, ok] - Minimum
    # ok が 最終的な答え
    ok = N
    ng = -1
    while abs(ok - ng) > 1:
        mid = (ok + ng) // 2
        n = mid
        dp = [0] * (K + 1)
        dp[0] = 1
        for i in range(N):
            a = A[i]
            if i == n or a >= K:
                continue
            for j in range(K, a - 1, -1):
                dp[j] |= dp[j - a]
        rst = any(dp[k] for k in range(max(0, K - A[n]), K))
        if rst:
            ok = mid
        else:
            ng = mid
    print(ok)


main()
# Original solution
import sys

sys.setrecursionlimit(4100000)

def biser(lst,func):
    n=len(lst)
    nh=n//2
    if n==1:
        if func(lst[0]):
            return lst[0]
        else:
            return -1
    if func(lst[nh]):
        return biser(lst[nh:],func)
    else:
        return biser(lst[:nh],func)

def findminsum(lst,K,N):
    inf=10**6
    dp=[[inf]*N for s in range(K+1)]
    for s in range(K+1):
        for j in range(N):
            if j==0 and s<=lst[j]:
                dp[s][j]=lst[0]
            elif s>lst[j] and j>0:
                dp[s][j]=min(dp[s-lst[j]][j-1]+lst[j], dp[s][j-1])
            elif s<=lst[j] and j>0:
                dp[s][j]=min(lst[j],dp[s][j-1])
    # print(lst)
    # print(dp[0][:])
    # print(dp[1][:])
    # print(dp[K][:])
    return dp[K][N-1]


def main():
    N,K=list(map(int,sys.stdin.readline().strip().split()))
    cards=list(map(int,sys.stdin.readline().strip().split()))
    # cards=list(filter(lambda x:x<K,cards))
    # N=len(cards)
    cards.sort()
    ci=list(range(N))
    def inneccesity(h):
        if cards[h]>=K:
            return False
        else:
            c=cards[h]
            cards[h]=0
            ret=findminsum(cards,K-c,N)>=K
            cards[h]=c
            return ret
    #nn=0
    nn=biser(ci,inneccesity)
    # for i in range(N):
    #     if cards[i]<K:
    #         c=cards[i]
    #         cards[i]=0
    #         if findminsum(cards,K-c,N)>=K:
    #             nn+=1
    #         cards[i]=c
    #     else:
    #         break
    print((nn+1))

if __name__=='__main__':
    main()


# Optimized solution
#4 9
#1 3 5 6
#の時に1（正解は0）と出力されるがACになる

N, K = list(map(int, input().split()))
a=list(map(int, input().split()))
a.sort()
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

def biser(lst,func):
    n=len(lst)
    nh=n//2
    if n==1:
        if func(lst[0]):
            return lst[0]
        else:
            return -1
    if func(lst[nh]):
        return biser(lst[nh:],func)
    else:
        return biser(lst[:nh],func)

def mkns(a,s,m):
    if a==0:
        return s
    else:
        return (((s+1)<<a)|s) & m

def main():
    N,K=list(map(int,sys.stdin.readline().strip().split()))
    a=list(map(int,sys.stdin.readline().strip().split()))
    a.sort()
    ss=[0]*(N+1)
    pm=(1<<K)-1
    mask=lambda c:(1<<K)-(1<<c)
    nn=0
    def isunnec(i): 
        if a[i]>=K:
            return False
        for j in range(i+1,N):
            if a[j]>=K:
                break
            ss[i]=mkns(a[j],ss[i],pm)
        # print(bin(ss[i]), bin(mask(K-c)),ss[i]&mask(K-c))
        if ss[i]&mask(K-a[i])==0:
            return True
        return False
    
    for i in range(N):
         if a[i]>=K:
             break
         ss[i+1]=mkns(a[i],ss[i],pm)
         if isunnec(i):
             nn+=1
        # for j in range(i+1,N):
        #     if a[j]>=K:
        #         break
        #     ss[i]=mkns(a[j],ss[i],pm)
        # # print(bin(ss[i]), bin(mask(K-c)),ss[i]&mask(K-c))
        # if ss[i]&mask(K-a[i])==0:
        #     nn+=1
    # nn=biser(list(range(N)),isunnec)+1
    # print(list(map(bin,ss)))
    print(nn)

if __name__=='__main__':
    main()


# Optimized solution
import sys

def biser(lst,func):
    n=len(lst)
    nh=n//2
    if n==1:
        if func(lst[0]):
            return lst[0]
        else:
            return -1
    if func(lst[nh]):
        return biser(lst[nh:],func)
    else:
        return biser(lst[:nh],func)

def mkns(a,s,m):
    if a==0:
        return s
    else:
        return (((s+1)<<a)|s) & m

def main():
    N,K=list(map(int,sys.stdin.readline().strip().split()))
    a=list(map(int,sys.stdin.readline().strip().split()))
    a.sort()
    ss=[0]*(N+1)
    pm=(1<<K)-1
    mask=lambda c:(1<<K)-(1<<c)
    nn=0
    def isunnec(i):
        if a[i]>=K:
            return False
        for j in range(i+1,N):
            if a[j]>=K:
                break
            ss[i]=(((ss[i]+1)<<a[j])|ss[i]) & pm
        # print(bin(ss[i]), bin(mask(K-c)),ss[i]&mask(K-c))
        if ss[i]&mask(K-a[i])==0:
            return True
        return False
    
    for i in range(N):
        if a[i]>=K:
            break
        ss[i+1]=(((ss[i]+1)<<a[i])|ss[i]) & pm
        #if isunnec(i):
        #     nn+=1
        #for j in range(i+1,N):
        #    if a[j]>=K:
        #        break
        #    ss[i]=mkns(a[j],ss[i],pm)
        ##print(bin(ss[i]), bin(mask(K-c)),ss[i]&mask(K-c))
        #if ss[i]&mask(K-a[i])==0:
        #    nn+=1
    #m=len(list(filter(lambda x:x<K, a)))
    nn=biser(list(range(N)),isunnec)+1
    #print(list(map(bin,ss)))
    print(nn)

if __name__=='__main__':
    main()
# Original solution
from itertools import accumulate

def main():
    N, K = list(map(int, input().split()))
    As = list(map(int, input().split()))
    
    dp = [0] * (K+1)
    dp[0] = 1
    nonzeros = [1]
    for a in As:
        ndp = []
        nonzero = 0
        for i in range(K+1):
            t = dp[i] if i < a else dp[i] + dp[i-a]
            if t == 0:
                ndp.append(0)
            else:
                nonzero |= 1 << i
                ndp.append(1)
        nonzeros.append(nonzero)
        dp = ndp
    dp = [0] * (K+1)
    dp[0] = 1
    acc = list(accumulate(dp)) + [0]
    ans = 0
    for i in range(N, 0, -1):
        a = As[i-1]
        ndp = []
        for j in range(K+1):
            t = dp[j] if j < a else dp[j] + dp[j-a]
            ndp.append(0 if t == 0 else 1)
        dp = ndp
        if a < K:
            nonzero = nonzeros[i-1]
            for y in range(K+1):
                if nonzero & 1:
                    t = K-y-a-1
                    if acc[K-y-1] > acc[t if t >= 0 else -1]:
                        break
                nonzero >>= 1
            else:
                ans += 1
        acc = list(accumulate(dp)) + [0]
    
    print(ans)

main()


# Optimized solution
from itertools import accumulate

def main():
    N, K = list(map(int, input().split()))
    As = list(map(int, input().split()))
    
    nonzeros = [1]
    for a in As:
        ndp = nonzeros[-1]
        if a <= K:
            ndp |= (nonzeros[-1] % (1 << (K-a))) << a
        nonzeros.append(ndp)
    dp = [0] * (K+1)
    dp[0] = 1
    acc = list(accumulate(dp)) + [0]
    ans = 0
    for i in range(N, 0, -1):
        a = As[i-1]
        ndp = []
        for j in range(K+1):
            t = dp[j] if j < a else dp[j] + dp[j-a]
            ndp.append(0 if t == 0 else 1)
        dp = ndp
        if a < K:
            nonzero = nonzeros[i-1]
            for y in range(K+1):
                if nonzero & 1:
                    t = K-y-a-1
                    if acc[K-y-1] > acc[t if t >= 0 else -1]:
                        break
                nonzero >>= 1
            else:
                ans += 1
        acc = list(accumulate(dp)) + [0]
    
    print(ans)

main()
# Original solution
import bisect


n, k = list(map(int, input().split()))
a = list(map(int, input().split()))

a = sorted(a)
end = bisect.bisect_right(a, k)
a = a[0:end]
n = len(a)

#rightの部分和の集合を予め求めておく
right_subset_sum = [None] * (n+1)
right_subset_sum[-1] = set([0])
for i in range(n)[::-1]:
    a_i = a[i]
    tmp_set = set([])
    if a_i <= k:
        tmp_set.add(a_i)
    for j in right_subset_sum[i+1]:
        if j + a_i <= k:
            tmp_set.add(j + a_i)
    right_subset_sum[i] = right_subset_sum[i+1] | tmp_set

ans = 0
left_subset_sum = set([0])

for i in range(n):
    a_i= a[i]
    li = sorted(list(right_subset_sum[i+1]))
    for num in left_subset_sum:
        left = k - a_i - num
        right = k - num
        if bisect.bisect_left(li, right) - bisect.bisect_left(li, left) > 0:
            break
    else:
        ans += 1
    #leftの集合にa_iを含めた部分和を追加する
    tmp_set = set([])
    if a_i <= k:
        tmp_set.add(a_i)
    for j in left_subset_sum:
        if j + a_i <= k:
            tmp_set.add(j + a_i)
    left_subset_sum = left_subset_sum | tmp_set
print(ans)


# Optimized solution
import bisect


n, k = list(map(int, input().split()))
a = list(map(int, input().split()))
a = sorted(a)
end = bisect.bisect_right(a, k)
a = a[0:end]
n = len(a)

def subset_sum(mid):
    if a[mid] >= k:
        return True
    dp = [False]*k
    dp[0] = True    
    for i in range(n):
        if i == mid:
            continue
        for j in range(k)[::-1]:
            if j - a[i] < 0:
                break
            else:
                dp[j] |= dp[j - a[i]]
 
    return sum(dp[k-a[mid]:])
  
ok = -1
ng = n
while abs(ng - ok) > 1:
    mid = (ok + ng) // 2
    if subset_sum(mid):
        ng = mid
    else:
        ok = mid
print(ng)
# Original solution
import sys
input = sys.stdin.buffer.readline


def solve(mid):
    """のぞいてもいいカードならTrueを返す"""
    dp = [False] * (k + 1)
    dp[0] = True
    if k <= a[mid]:
        return False
    for i, weight in enumerate(a):
        if i == mid:
            continue
        for w in range(k + 1)[::-1]:
            if w - weight < 0:
                continue
            dp[w] |= dp[w - weight]

    return True not in dp[k - a[mid]:k]
     

n, k = list(map(int, input().split()))
a = list(map(int, input().split()))

a.sort()
ok = 0
ng = n
if not solve(ok):
    print((0))
    exit()

while abs(ok - ng) > 1:
    mid = (ok + ng) // 2
    if solve(mid):
        ok = mid
    else:
        ng = mid
print((ok + 1))

# Optimized solution
import sys
input = sys.stdin.buffer.readline


def solve(mid):
    """のぞいてもいいカードならTrueを返す"""
    dp = 1
    mask = (1 << k) - 1
    if k <= a[mid]:
        return False
    for i, weight in enumerate(a):
        if i == mid:
            continue
        dp |= dp << min(weight, k + 10)
        dp &= mask
    return dp >> (k - a[mid]) == 0
     

n, k = list(map(int, input().split()))
a = list(map(int, input().split()))

a.sort()
ok = 0
ng = n
if not solve(ok):
    print((0))
    exit()

while abs(ok - ng) > 1:
    mid = (ok + ng) // 2
    if solve(mid):
        ok = mid
    else:
        ng = mid

print((ok + 1))
# Original solution
def main():
    n,k = list(map(int, input().split()))
    a = list(map(int, input().split()))

    a = [i for i in a if i <k]
    a.sort()
    n = len(a)

    DP1 = [[False]*(k+1)]
    DP1[0][0] = True
    DP2 = [[False]*(k+1)]
    DP2[0][0] = True
    b = a[::-1]

    for i in range(n):
        DP1.append(DP1[i][:])
        DP2.append(DP2[i][:])
        for j in range(k+1):
            if DP1[i][j] and a[i]+j <= k:
                DP1[i+1][a[i]+j] = True
            if DP2[i][j] and b[i]+j <= k:
                DP2[i+1][b[i]+j] = True

    for i in range(n+1):
        q = [0]
        for j in range(k+1):
            q.append(q[-1]+int(DP2[i][j]))
        DP2[i] = q

    ans = 0
    for i in range(n):
        use = False
        for j in range(k+1):
            if not DP1[i][j]:
                continue
            left = max(0, k-a[i]-j)
            right = k-j
            if DP2[n-i-1][right] - DP2[n-i-1][left]:
                use = True
                break
        if not use:
            ans += 1

    print(ans)


if __name__ == "__main__":
    main()

# Optimized solution
def main():
    def check(m):
        DP = [False]*(k+1)
        DP[0] = True
        for i in range(n):
            if i == m:
                continue
            for j in reversed(list(range(k+1-a[i]))):
                DP[a[i]+j] = DP[a[i]+j] or DP[j]
        return any(DP[i] for i in range(k-a[m], k))

    n,k = list(map(int, input().split()))
    a = list(map(int, input().split()))

    a = [i for i in a if i <k]
    a.sort()
    n = len(a)

    left = -1
    right = n

    while right-left > 1:
        mid = (right+left)//2
        if check(mid):
            right = mid
        else:
            left = mid

    print(right)

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

a = sorted(a)
ans = N
for i in range(N-1, -1, -1) :
    psum = 0
    for j in range(i, -1, -1) :
        if psum+a[j] < K :
            psum += a[j]
        else :
            ans = min(ans, j)

print(ans)

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

a = sorted(a)
ans = N
psum = 0
for i in range(N-1, -1, -1) :
    if psum+a[i] < K :
        psum += a[i]
    else :
        ans = min(ans, i)

print(ans)