CodeEff/ECCO huggingface dataset:
# Original solution
import heapq

n, need = list(map(int, input().split()))
a = [list(map(int, input().split())) for _ in range(n)]

ret = float('inf')
for mask in range(1 << n):
    total = 0
    count = 0
    pq = []
    for bit in range(n):
        num, bonus = a[bit]
        points = (bit + 1) * 100
        if (mask >> bit) & 1:
            total += points * num + bonus
            count += num
        else:
            for i in range(num):
                heapq.heappush(pq, -points)
    while total < need and pq:
        total -= heapq.heappop(pq)
        count += 1
    if total >= need:
        ret = min(ret, count)

print(ret)

# Optimized solution
n, need = list(map(int, input().split()))
a = [list(map(int, input().split())) for _ in range(n)]

ret = float('inf')
for mask in range(1 << n):
    total = 0
    count = 0
    for bit in range(n):
        if (mask >> bit) & 1:
            num, bonus = a[bit]
            points = (bit + 1) * 100
            total += points * num + bonus
            count += num
    for bit in range(n - 1, -1, -1):
        if (mask >> bit) & 1 == 0:
            num = a[bit][0]
            points = (bit + 1) * 100
            for i in range(num):
                if total >= need:
                    break
                total += points
                count += 1
    if total >= need:
        ret = min(ret, count)

print(ret)
# Original solution
import sys

read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines
sys.setrecursionlimit(10 ** 9)
INF = 1 << 60
MOD = 1000000007


def main():
    D, G, *PC = list(map(int, read().split()))
    P = PC[::2]
    C = PC[1::2]

    ans = INF
    for mask in range(1 << D):
        problems = score = 0
        available = [False] * D
        for i in range(D):
            if mask & (1 << i):
                problems += P[i]
                score += 100 * (i + 1) * P[i] + C[i]
            else:
                available[i] = True

        if score >= G:
            if ans > problems:
                ans = problems
            continue

        for i in range(D - 1, -1, -1):
            if not available[i]:
                continue
            if score + 100 * (i + 1) * P[i] + C[i] < G:
                problems += P[i]
                score += 100 * (i + 1) * P[i] + C[i]
            else:
                n = (G - score + 100 * (i + 1) - 1) // (100 * (i + 1))
                problems += n
                score += 100 * (i + 1) * n
                break

        if score >= G and ans > problems:
            ans = problems

    print(ans)
    return


if __name__ == '__main__':
    main()


# Optimized solution
import sys

read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines
sys.setrecursionlimit(10 ** 9)
INF = 1 << 60
MOD = 1000000007


def main():
    D, G, *PC = list(map(int, read().split()))
    P = PC[::2]
    C = PC[1::2]

    ans = INF
    for mask in range(1 << D):
        problems = score = 0
        for i in range(D):
            if mask & (1 << i):
                problems += P[i]
                score += 100 * (i + 1) * P[i] + C[i]
            else:
                idx_max = i

        if score >= G:
            if ans > problems:
                ans = problems
            continue

        if score + 100 * (idx_max + 1) * (P[idx_max] - 1) >= G:
            problems += (G - score + 100 * (idx_max + 1) - 1) // (100 * (idx_max + 1))
            if ans > problems:
                ans = problems

    print(ans)
    return


if __name__ == '__main__':
    main()
# Original solution
from collections import deque
import itertools, math
d,g = list(map(int,input().split()))
pc = [list(map(int,input().split())) for _ in range(d)]
g /= 100

pat = list(itertools.permutations(list(range(d))))
ans = sum([pc[x][0] for x in range(d)])

def dfs(k, point, cnt, pat):
  global ans
  i = pat[k]
  
  cnt += min(pc[i][0], math.ceil((g-point)/(i+1)))
  point += min(pc[i][0], math.ceil((g-point)/(i+1))) * (i+1)
  point += pc[i][1]//100
  #print(k,i,point,cnt)
  if point >= g:  
    ans  = min(ans, cnt)
    return
  else:
    if k < d-1:
      dfs(k+1, point, cnt, pat)
      

for p in pat:
  dfs(0, 0, 0, list(p))

print(ans)

# Optimized solution
from collections import deque
import itertools, math
d,g = list(map(int,input().split()))
pc = [list(map(int,input().split())) for _ in range(d)]
g /= 100

#ans = sum([pc[x][0] for x in range(d)])
ans = float('inf')
for bit in range(1<<d):
  cnt = 0
  point = 0
  pat = set(range(1,d+1))
  
  for i in range(d):
    if bit & (1<<i):
      point += pc[i][0]*(i+1) + pc[i][1]//100
      cnt += pc[i][0]
      pat.discard(i+1)
  
  if point < g:
      next = max(pat)
      n = min(pc[next-1][0], math.ceil((g - point)/(next)))
      cnt += n
      point += n*(next)
    
  if point >= g:
      #print(ans,cnt)
      ans = min(ans,cnt)


print(ans)
# Original solution
from collections import deque
import itertools, math
d,g = list(map(int,input().split()))
pc = [list(map(int,input().split())) for _ in range(d)]
g /= 100

#ans = sum([pc[x][0] for x in range(d)])
ans = float('inf')
for bit in range(1<<d):
  cnt = 0
  point = 0
  pat = set(range(1,d+1))
  
  for i in range(d):
    if bit & (1<<i):
      point += pc[i][0]*(i+1) + pc[i][1]//100
      cnt += pc[i][0]
      pat.discard(i+1)
  
  if point < g:
      next = max(pat)
      n = min(pc[next-1][0], math.ceil((g - point)/(next)))
      cnt += n
      point += n*(next)
    
  if point >= g:
      #print(ans,cnt)
      ans = min(ans,cnt)


print(ans)


# Optimized solution
d,g  = list(map(int,input().split()))
pc = [list(map(int,input().split())) for _ in range(d)]

ans = float('inf')

for bit in range(1<<d):
  sum = 0
  cnt = 0
  rem = set(range(d))
  for i in range(d):
    if bit & 1<<i:
      sum += pc[i][0]*(i+1)*100 + pc[i][1]
      cnt += pc[i][0]
      rem.discard(i)
    
  if sum < g:
    u = max(rem)
    n = min(pc[u][0],  -( -(g-sum)//((u+1)*100) ))
    cnt += n
    sum += n*(u+1)*100
    
  if sum >= g:
    ans = min(ans, cnt)
    

print(ans)
# Original solution
from math import ceil

D, G = [int(t) for t in input().split()]
p = []
c = []
for i in range(D):
    p_, c_ = [int(t) for t in input().split()]
    p.append(p_)
    c.append(c_)

def solve(G, i):
    """100i点以下の問題だけでGを達成する最小問題数"""
    if i <= 0:
        return float('inf')
    #最も配転が高い問題で総合点を超えることができるか確認
    n = min(ceil(G / (100 * i)), p[i - 1])
    s = 100 * i * n
    #もし総合展を超えることができるときの問題数がボーナス点に達するならば足す
    if n == p[i - 1]:
        s += c[i - 1]
    if G > s:
        n += solve(G - s, i - 1)
    return min(n, solve(G, i - 1))

print((solve(G, D)))

# Optimized solution
from math import ceil
D,G = list(map(int,input().split()))
list = [list(map(int,input().split())) for _ in range(D)]

def dfs(G,i):
    if i <= 0:
        return float('inf')
    n = min(ceil(G/(100*i)),list[i-1][0])
    s = 100*i*n
    if n == list[i-1][0]:
        s += list[i-1][1]
    if G > s:
        n += dfs(G-s,i-1)
    return min(n,dfs(G,i-1))

print((dfs(G,D)))
# Original solution
d, g = list(map(int, input().split()))
pc = [0] + [[int(i) for i in input().split()] for i in range(d)]

def dfs(g, i):
    if i == 0:
        return 10 ** 12
    
    n = min(g // (100 * i), pc[i][0])
    score = n * 100 * i
    
    if n == pc[i][0]:
        score += pc[i][1]
        
    if g > score:
        n += dfs(g - score, i - 1)
        
    return min(n, dfs(g, i - 1))

print((dfs(g, d)))

# Optimized solution
d, g = list(map(int, input().split()))
PC = [0] + [[int(i) for i in input().split()] for i in range(d)]

def dfs(g, i):
    if i == 0:
        return 10 ** 12
    
    n = min(g // (100 * i), PC[i][0])
    score = n * 100 * i
    
    if n == PC[i][0]:
        score += PC[i][1]
        
    if g > score:
        n += dfs(g - score, i - 1)
        
    return min(n, dfs(g, i - 1))

print((dfs(g, d)))
# Original solution
D , G = list(map(int,input().split()))
questions = []
for i in range(D):
    p , c = list(map(int,input().split()))
    questions.append([p,c])

ans = float("inf")
for bit in range(2 ** D):
    tmp_ans = 0
    tmp_sum = 0
    for j in range(D):
        if bit >> j & 1:
            tmp_sum += questions[j][0] * 100 * (j + 1) + questions[j][1]
            tmp_ans += questions[j][0]
    if tmp_sum < G:
        for j in range(D - 1 , -1 , -1):
            if bit >> j & 1:
                continue
            else:
                for k in range(questions[j][0]):
                    tmp_ans += 1
                    tmp_sum += 100 * (j + 1)
                    if tmp_sum >= G:
                        break
                if tmp_sum >= G:
                    break
    if tmp_ans < ans and tmp_sum >= G:
        ans = tmp_ans
print(ans)

# Optimized solution
D , G = list(map(int,input().split()))
bonus = []
question_cnt = []
for i in range(D):
    p , c = list(map(int,input().split()))
    question_cnt.append(p)
    bonus.append(c)
ans = float('inf')
for bit in range(2 ** D):
    sum_val = 0
    tmp_ans = 0
    Flag = False
    for j in range(D):
        if bit >> j & 1:
            sum_val += question_cnt[j] * (j + 1) * 100 + bonus[j]
            tmp_ans += question_cnt[j]
    if sum_val < G:
        for j in range(D-1 , - 1 , -1):
            if Flag:
                break
            if not bit >> j & 1:
                Flag = True
                for k in range(question_cnt[j]):
                    sum_val += (j + 1) * 100
                    tmp_ans += 1
                    if sum_val >= G:
                        break
    if tmp_ans < ans and sum_val >= G:
        ans = tmp_ans
print(ans)
# Original solution
import math

D, G = list(map(int, input().split()))
lst = [list(map(int, input().split())) for _ in range(D)]

ret = 1000 ** 10
for i in range(2 ** D):
    total = 0
    cnt = 0
    digit = 1
    for p in range(D):
        if (digit << p) & i:
            cnt += lst[p][0]
            total += lst[p][0] * (p + 1) * 100 + lst[p][1]

    for p in range(D)[::-1]:
        if not ((digit << p) & i):
            delta = max(0, G - total)
            n = min(math.ceil(delta / ((p + 1) * 100)), lst[p][0])
            cnt += n
            total += n * (p + 1) * 100
    ret = min(ret, cnt)
print(ret)


# Optimized solution
import math

D, G = list(map(int, input().split()))
lst = [list(map(int, input().split())) for _ in range(D)]

ret = 1000 ** 10
for i in range(2 ** D):
    total = 0
    cnt = 0
    for p in range(D):
        if (i >> p) & 1:
            cnt += lst[p][0]
            total += lst[p][0] * (p + 1) * 100 + lst[p][1]

    for p in range(D)[::-1]:
        delta = G - total
        if delta <= 0:
            break
        if not ((i >> p) & 1):
            n = min(math.ceil(delta / ((p + 1) * 100)), lst[p][0])
            cnt += n
            total += n * (p + 1) * 100
    ret = min(ret, cnt)
print(ret)
# Original solution
d,g=list(map(int,input().split()))
g=g//100
pc=[list(map(int,input().split())) for i in range(d)]
P=0
C=0#合計
for i in range(d):
    pc[i][1]=pc[i][1]//100
    C=(C+pc[i][1]+pc[i][0]*(i+1))
    P+=pc[i][0]
dp=[10000000]*(C+1)
for i in range(d):
    dp_sub=[10000000]*(C+1)
    for j in range(C+1):
        if j==0:
            for k in range(1,pc[i][0]+1):
                if k!=pc[i][0]:
                    dp_sub[k*(i+1)]=k
                else:
                    dp_sub[k*(i+1)+pc[i][1]]=k
        elif dp[j]!=10000000:
            for k in range(1,pc[i][0]+1):
                if k!=pc[i][0]:
                    dp_sub[j+k*(i+1)]=min(dp[j]+k,dp_sub[j+k*(i+1)])
                else:
                    dp_sub[j+k*(i+1)+pc[i][1]]=min(dp[j]+k,dp_sub[j+k*(i+1)+pc[i][1]])

    for j in range(C+1):
        if dp_sub[j]!=0:
            dp[j]=min(dp[j],dp_sub[j])
m=P
for i in range(g,C+1):
    if dp[i]!=0:
        m=min(m,dp[i])
print(m)


# Optimized solution
import math
d,g=list(map(int,input().split()))
pc=[list(map(int,input().split())) for i in range(d)]
ans=10000000000000000000
for i in range(1<<d):
    s=0
    ans_=0
    for j in range(d):
        if (i>>j)&1:
            s+=(pc[j][1]+pc[j][0]*100*(j+1))
            ans_+=pc[j][0]
    #print(s,ans_)
    if s>=g:
        ans=min(ans,ans_)
    else:
        for j in range(d-1,-1,-1):
            if not((i>>j)&1):
                if s+(pc[j][0]*100*(j+1))>=g:
                    h=-((s-g)//(100*(j+1)))
                    s+=(h*100*(j+1))
                    ans_+=h
                    ans=min(ans,ans_)
                    break
                else:
                    break
print(ans)
#ansとans_
#謎のWA
# Original solution
D,G = list(map(int,input().split()))
PC = []

L = []

t = 10 ** 9
m = 0

for i in range(1,D + 1):
  p,c = list(map(int,input().split()))
  s = 0
  pc = []
  for j in range(p):
    s += i * 100
    if j == p - 1:
      s += c
      L.append([j + 1,s])
    if s >= G and j + 1 < t:
      t = j + 1
    pc.append([j + 1,s])
  PC.append(pc)

def recur(problems):
  #探索の終了
  if len(problems) == D:
    ans = 10 ** 9
    score = 0
    times = 0
    #全部使用した問題セットの合計点と回答数を記録
    for j in range(D):
      if problems[j] == 1:
        score += L[j][1]
        times += L[j][0]
    #全問全回答の例を除く
    if score >= G:
      ans = min(ans,times)
      return ans
    #残りの数以上となる回答数のうち最小のものが見つかれば更新し
    #全回答の回答数に足す
    else:
      remain = G - score
      if remain <= max([L[i][1] for i in range(D) if problems[i] == 0]):
        for k in range(D):
          if problems[k] == 0:
            for l in range(len(PC[k])):
              if remain <= PC[k][l][1] and ans >= PC[k][l][0]:
                ans = PC[k][l][0]
        ans += times
        return ans
      else:
        return 10 ** 9
  
  else:
    #問題セットを全部使う
    ret1 = recur(problems + [1])
    #使わない
    ret2 = recur(problems + [0])
    
    return min(ret1,ret2)

print((recur([])))



# Optimized solution
import math
D, G = list(map(int, input().split()))

PC = []
for _ in range(D):
    p, c = list(map(int, input().split()))
    PC.append([p, c])

ans = 10 ** 9

#全部解く・解かないが2のD乗通りになる
for i in range(2 ** D):
    score = 0
    time = 0
    maxj = -1
    #全部解く場合
    for j in range(D):
    #jケタ落としていき、jケタめ == 1であれば、つまりj番目の問題セットを全部解いていれば
        if ((i >> j) & 1):
            score += (j + 1) * PC[j][0] * 100 + PC[j][1]
            time += PC[j][0]
        #全てを解かなかった問題セットのうち最も大きいj
        ##全て解かない問題セットは1つでよく、最大の素点のもの=一番大きいjでよい
        else:
            maxj = max(maxj,j)
    #全てを全部解いた場合
    if maxj == -1:
      ans = min(ans, time)
    #jケタめを全て使わずにG以上のスコアとなった場合
    elif score + (maxj + 1) * (PC[maxj][0] - 1) * 100 >= G:
        #必要な最小問題数を小数点切り上げで求める
        ##残りが500点であったとき、300点問題なら2問、200点問題なら3問解けばよい
        time += max(0, math.ceil((G - score) / (maxj + 1) / 100))
        #最小のものを更新していく
        ans = min(ans, time)

print(ans)
# Original solution
from itertools import *
from math import *

D, G = list(map(int, input().split()))
probs = [list(map(int, input().split())) for _ in range(D)]
seq = list(range(D))
x = list(permutations(seq, D))
#print(x)
ans = float("inf")
G2=G
for i in range(len(x)):
    cand = x[i]
    cnt = 0
    G=G2
    for j in range(D):
        ind = cand[j]
        probpoint = (ind + 1) * 100
        if G<=0:
            break
        if G <= probpoint * (probs[ind][0] - 1):
            cnt = cnt + ceil(G / probpoint)
            G=G-probpoint*ceil(G / probpoint)
        else:
            cnt=cnt+probs[ind][0]
            G=G-(probpoint * probs[ind][0]+probs[ind][1])
    ans=min(ans,cnt)
print(ans)




# Optimized solution
from itertools import *
from math import *

D, G = list(map(int, input().split()))
probs = [list(map(int, input().split())) for _ in range(D)]
seq = list(range(D))
x = list(permutations(seq, D))
#print(x)
ans = float("inf")
G2=G
for cand in x:
    cnt = 0
    G=G2
    for ind in cand:
        probpoint = (ind + 1) * 100
        if G<=0:
            break
        if G <= probpoint * (probs[ind][0] - 1):
            cnt = cnt + ceil(G / probpoint)
            G=G-probpoint*ceil(G / probpoint)
        else:
            cnt=cnt+probs[ind][0]
            G=G-(probpoint * probs[ind][0]+probs[ind][1])
    ans=min(ans,cnt)
print(ans)
# Original solution
from itertools import accumulate
from operator import add

N, K = list(map(int, input().split()))
K2 = 2 * K

# Gss[i][j]: 「市松模様の黒い部分の右上のマス」が(i,j)のとき、満たせる要望の個数
Gss = [[0] * K2 for i in range(K2)]

for i in range(N):
    x, y, c = input().split()
    x, y = int(x), int(y)

    # 要望を「0<=x<2K, 0<=y<K, 'B'」に変換する
    if c == 'W':
        x -= K
    x, y = x % K2, y % K2

    if y >= K:
        x, y = (x - K) % K2, y - K

    # 要望を満たす「市松模様の黒い部分の右上のマス」に対して、+1する
    # （後で累積和を取る）
    Gss[x][y] += 1
    Gss[x][y - K] += -1
    if x != K:
        Gss[x - K][y - K] += 1
        Gss[x - K][y] += -1
    if x > K:
        Gss[0][y] += 1
        Gss[0][y - K] += -1

# 累積和を取る
Gss = [list(accumulate(Gs)) for Gs in Gss]
Gss = [list(accumulate(Gs)) for Gs in zip(*Gss)]
Gss = list(map(list, list(zip(*Gss)))) # 転置

# 「K<=y<2K」の部分を、「0<=y<K」に重ね合わせる
Gss = [list(map(add, Gss[i][:K], Gss[i - K][K:])) for i in range(K2)]

# Gssの最大値が答え
print((max(list(map(max, Gss)))))


# Optimized solution
from itertools import accumulate
from operator import add

N, K = list(map(int, input().split()))
K2 = 2 * K

# Gss[i][j]: 「市松模様の黒い部分の右上のマス」が(i,j)のとき、満たせる要望の個数
Gss = [[0] * K2 for i in range(K2)]

for i in range(N):
    x, y, c = input().split()
    x, y = int(x), int(y)

    # 要望を「0<=x<2K, 0<=y<K, 'B'」に変換する
    if c == 'W':
        x -= K
    x, y = x % K2, y % K2

    if y >= K:
        x, y = (x - K) % K2, y - K

    # 要望を満たす「市松模様の黒い部分の右上のマス」に対して、+1する
    # （後で累積和を取る）
    Gss[x][y] += 1
    Gss[x][y - K] += -1
    if x != K:
        Gss[x - K][y - K] += 1
        Gss[x - K][y] += -1
    if x > K:
        Gss[0][y] += 1
        Gss[0][y - K] += -1

# 累積和を取る
Gss = [accumulate(Gs) for Gs in Gss]
Gss = [accumulate(Gs) for Gs in zip(*Gss)]
Gss = list(map(list, list(zip(*Gss)))) # 転置

# 「K<=y<2K」の部分を、「0<=y<K」に重ね合わせる
Gss = [list(map(add, Gss[i][:K], Gss[i - K][K:])) for i in range(K2)]

# Gssの最大値が答え
print((max(list(map(max, Gss)))))
# Original solution
from collections import defaultdict

n, k = list(map(int, input().split()))
k2 = k * 2
requires = defaultdict(lambda: [0, 0])
for i in range(n):
    x, y, c = input().split()
    x, y = int(x), int(y)
    rx, ry = x % k2, y % k2
    b = c == 'B'
    if rx > k:
        if ry > k:
            rx -= k
            ry -= k
        else:
            rx -= k
            b = not b

    requires[rx, ry][b] += 1

ans = 0
for dx in range(k):
    for dy in range(k):
        cnt_w, cnt_b = 0, 0
        for (x, y), (w, b) in list(requires.items()):
            f = ((x + dx) // k + (y + dy) // k) & 1
            if f:
                cnt_w += b
                cnt_b += w
            else:
                cnt_w += w
                cnt_b += b
        ans = max(ans, cnt_b, cnt_w)
print(ans)


# Optimized solution
from itertools import accumulate

n, k = list(map(int, input().split()))
k2 = k * 2
req_b = [[0] * k for _ in range(k)]
req_w = [[0] * k for _ in range(k)]
bc, wc = 0, 0
for i in range(n):
    x, y, c = input().split()
    x, y = int(x), int(y)
    rx, ry = x % k2, y % k2
    b = c == 'B'
    if rx >= k:
        rx -= k
        if ry >= k:
            ry -= k
        else:
            b = not b
    elif ry >= k:
        ry -= k
        b = not b
    if b:
        req_b[rx][ry] += 1
        bc += 1
    else:
        req_w[rx][ry] += 1
        wc += 1

req_b[0] = list(accumulate(req_b[0]))
req_w[0] = list(accumulate(req_w[0]))

for i in range(1, k):
    req_b[i][0] += req_b[i - 1][0]
    req_w[i][0] += req_w[i - 1][0]
    for j in range(1, k):
        req_b[i][j] += req_b[i][j - 1] + req_b[i - 1][j] - req_b[i - 1][j - 1]
        req_w[i][j] += req_w[i][j - 1] + req_w[i - 1][j] - req_w[i - 1][j - 1]

ans = 0
for dx in range(k):
    dxk_b = req_b[dx][-1]
    dxk_w = req_w[dx][-1]
    for dy in range(k):
        b1 = req_b[dx][dy]
        b2 = bc - req_b[k - 1][dy] - dxk_b + b1
        w1 = req_w[dx][dy]
        w2 = wc - req_w[k - 1][dy] - dxk_w + w1
        b, w = b1 + b2, w1 + w2
        ans = max(ans, b + wc - w, w + bc - b)
        # print(dx, dy, b, w, b + wc - w, w + bc - b)
print(ans)
# Original solution
from itertools import accumulate

n, k = list(map(int, input().split()))
k2 = k * 2
req_b = [[0] * k for _ in range(k)]
req_w = [[0] * k for _ in range(k)]
bc, wc = 0, 0
for i in range(n):
    x, y, c = input().split()
    x, y = int(x), int(y)
    rx, ry = x % k2, y % k2
    b = c == 'B'
    if rx >= k:
        rx -= k
        if ry >= k:
            ry -= k
        else:
            b = not b
    elif ry >= k:
        ry -= k
        b = not b
    if b:
        req_b[rx][ry] += 1
        bc += 1
    else:
        req_w[rx][ry] += 1
        wc += 1

req_b[0] = list(accumulate(req_b[0]))
req_w[0] = list(accumulate(req_w[0]))

for i in range(1, k):
    req_b[i][0] += req_b[i - 1][0]
    req_w[i][0] += req_w[i - 1][0]
    for j in range(1, k):
        req_b[i][j] += req_b[i][j - 1] + req_b[i - 1][j] - req_b[i - 1][j - 1]
        req_w[i][j] += req_w[i][j - 1] + req_w[i - 1][j] - req_w[i - 1][j - 1]

ans = 0
for dx in range(k):
    dxk_b = req_b[dx][-1]
    dxk_w = req_w[dx][-1]
    for dy in range(k):
        b1 = req_b[dx][dy]
        b2 = bc - req_b[k - 1][dy] - dxk_b + b1
        w1 = req_w[dx][dy]
        w2 = wc - req_w[k - 1][dy] - dxk_w + w1
        b, w = b1 + b2, w1 + w2
        ans = max(ans, b + wc - w, w + bc - b)
        # print(dx, dy, b, w, b + wc - w, w + bc - b)
print(ans)


# Optimized solution
from itertools import accumulate

n, k = list(map(int, input().split()))
k2 = k * 2
req_b = [[0] * k for _ in range(k)]
req_w = [[0] * k for _ in range(k)]
bc, wc = 0, 0
for i in range(n):
    x, y, c = input().split()
    x, y = int(x), int(y)
    rx, ry = x % k2, y % k2
    b = c == 'B'
    if rx >= k:
        rx -= k
        if ry >= k:
            ry -= k
        else:
            b = not b
    elif ry >= k:
        ry -= k
        b = not b
    if b:
        req_b[rx][ry] += 1
        bc += 1
    else:
        req_w[rx][ry] += 1
        wc += 1

req_b = [list(accumulate(req)) for req in req_b]
req_w = [list(accumulate(req)) for req in req_w]
req_b = [list(accumulate(req)) for req in zip(*req_b)]
req_w = [list(accumulate(req)) for req in zip(*req_w)]

ans = 0
kb, kw = req_b[-1], req_w[-1]
for dx, (dx_b, dx_w) in enumerate(zip(req_b, req_w)):
    dxk_b = dx_b[-1]
    dxk_w = dx_w[-1]
    for b1, w1, kyb, kyw in zip(dx_b, dx_w, kb, kw):
        b = bc - kyb - dxk_b + b1 * 2
        w = wc - kyw - dxk_w + w1 * 2
        a = b + wc - w
        ans = max(ans, a, n - a)
print(ans)