CodeEff/ECCO huggingface dataset:
# Original solution
import sys
# 10倍速いらしい
input = sys.stdin.readline

INF = float('inf')
MOD = 10 ** 9 + 7
EPS = 10 ** -7
sys.setrecursionlimit(1000000)

S = input().rstrip()
T = input().rstrip()

sn = len(S)
M = [dict() for _ in range(sn)]
for i, s in enumerate(S):
    for j in range(sn):
        M[(i - j + sn) % sn][s] = min(M[(i - j + sn) % sn].get(s, INF), j)
    for j in range(sn):
        if M[(i - j + sn) % sn][s] == 0:
            M[(i - j + sn) % sn][s] = M[(i - j + sn + 1) % sn][s] + 1


ans = 0
idx = sn - 1
for t in T:
    if M[idx].get(t, INF) == INF:
        print((-1))
        sys.exit()
    ans += M[idx][t]
    idx = (idx + M[idx][t]) % sn

print(ans)


# Optimized solution
import sys
import bisect

# 10倍速いらしい
input = sys.stdin.readline

INF = float('inf')
MOD = 10 ** 9 + 7
EPS = 10 ** -7
sys.setrecursionlimit(1000000)

S = input().rstrip()
T = input().rstrip()

sn = len(S)
d = dict()
for i, s in enumerate(S):
    d[s] = d.get(s, [])
    d[s].append(i)

nowidx = -1
loop = 0
for t in T:
    l = d.get(t, [])
    if len(l) == 0:
        print((-1))
        sys.exit()
    j = bisect.bisect_right(l, nowidx)
    if len(l) <= j:
        nowidx = l[0]
        loop += 1
    else:
        nowidx = l[j]

# print(loop, nowidx)
print((loop * sn + nowidx + 1))
# Original solution
import sys
stdin = sys.stdin

sys.setrecursionlimit(10 ** 7)

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

from collections import defaultdict
from bisect import bisect_right

s = ns()
t = ns()

ok = True

sset = set(list(s))
for ti in t:
    if ti not in sset:
        ok = False
        break

if not ok:
    print((-1))

else:
    n = len(s)

    charidx = defaultdict(list)

    for i, si in enumerate(s):
        charidx[si].append(i)
    for i, si in enumerate(s):
        charidx[si].append(n+i)

    ks = list(charidx.keys())

    move = [{ki: -1 for ki in ks} for _ in range(n)]

    for i, si in enumerate(s):
        for ki in ks:
            nexidx = bisect_right(charidx[ki], i)
            move[i][ki] = (charidx[ki][nexidx] - i) % (n+1)

    cur = s.index(t[:1])
    ans = cur
    for ti in t[1:]:
        nex = move[cur][ti]
        ans += nex
        cur = (cur + nex) % n

    print((ans+1))



# Optimized solution
import sys
stdin = sys.stdin

sys.setrecursionlimit(10 ** 7)

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

from collections import defaultdict
from bisect import bisect_right

s = ns()
t = ns()

ok = True

sset = set(list(s))
for ti in t:
    if ti not in sset:
        ok = False
        break

if not ok:
    print((-1))

else:
    n = len(s)

    charidx = defaultdict(list)

    for i, si in enumerate(s):
        charidx[si].append(i)
    for i, si in enumerate(s):
        charidx[si].append(n+i)

    ks = list(charidx.keys())

    move = [{ki: -1 for ki in ks} for _ in range(n)]

    for i, si in enumerate(s):
        for ki in ks:
            idxlist = charidx[ki]
            nexidx = bisect_right(idxlist, i)
            move[i][ki] = (idxlist[nexidx] - i) % (n+1)

    cur = s.index(t[:1])
    ans = cur
    for ti in t[1:]:
        nex = move[cur][ti]
        ans += nex
        cur = (cur + nex) % n

    print((ans+1))
# Original solution
import sys
stdin = sys.stdin

sys.setrecursionlimit(10 ** 7)

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

from collections import defaultdict
from bisect import bisect_right

s = ns()
t = ns()

ok = True

sset = set(list(s))
for ti in t:
    if ti not in sset:
        ok = False
        break

if not ok:
    print((-1))

else:
    n = len(s)

    charidx = defaultdict(list)

    for i, si in enumerate(s):
        charidx[si].append(i)
    for i, si in enumerate(s):
        charidx[si].append(n+i)

    ks = list(charidx.keys())

    move = [{ki: -1 for ki in ks} for _ in range(n)]

    for i, si in enumerate(s):
        for ki in ks:
            idxlist = charidx[ki]
            nexidx = bisect_right(idxlist, i)
            move[i][ki] = (idxlist[nexidx] - i) % (n+1)

    cur = s.index(t[:1])
    ans = cur
    for ti in t[1:]:
        nex = move[cur][ti]
        ans += nex
        cur = (cur + nex) % n

    print((ans+1))


# Optimized solution
import sys
stdin = sys.stdin

sys.setrecursionlimit(10 ** 7)

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

from bisect import bisect_right

s = ns()
t = ns()

# 判定
ok = True
sset = set(list(s))
tset = set(list(t))
for ti in tset:
    if ti not in sset:
        ok = False

if not ok:
    print((-1))
else:
    n = len(s)
    nex = [[] for _ in range(26)]
    sdouble = s + s
    orda = ord("a")
    for i, si in enumerate(sdouble):
        nex[ord(si) - orda].append(i)

    bef = t[:1]
    cur = s.index(t[:1])
    ans = cur

    for ti in t[1:]:
        chridx = ord(ti) - orda
        dest = bisect_right(nex[chridx], cur)
        ans += (nex[chridx][dest] - cur)
        cur = ans % n

    print((ans+1))
# Original solution
import sys,queue,math,copy,itertools,bisect,collections,heapq

def main():
    sys.setrecursionlimit(10**7)
    INF = 10**18
    MOD = 10**9 + 7
    LI = lambda : [int(x) for x in sys.stdin.readline().split()]
    NI = lambda : int(sys.stdin.readline())
    SI = lambda : sys.stdin.readline().rstrip()

    s = SI()
    t = SI()

    d = [[] for _ in range(26)]
    p = [0] * 26
    for i,x in enumerate(s):
        d[ord(x)-ord('a')].append(i+1)

    rev = 0
    a = 0
    for x in t:
        x = ord(x) - ord('a')
        if len(d[x]) == 0:
            print((-1))
            return

        c = p[x]
        while d[x][c] <= a:
            c += 1
            if c >= len(d[x]):
                rev += 1
                p = [0] * 26
                a = 0
                c = 0
        a = d[x][c]

    print((rev*len(s) + a))

if __name__ == '__main__':
    main()

# Optimized solution
import sys,queue,math,copy,itertools,bisect,collections,heapq

def main():
    sys.setrecursionlimit(10**7)
    INF = 10**18
    MOD = 10**9 + 7
    LI = lambda : [int(x) for x in sys.stdin.readline().split()]
    NI = lambda : int(sys.stdin.readline())
    SI = lambda : sys.stdin.readline().rstrip()

    s = SI()
    ds = s + s
    t = SI()

    z = [0] * 26
    nt = [[] for _ in range(len(ds))]

    for i in range(len(ds),0,-1):
        z[ord(ds[i-1])-ord('a')] = i
        nt[i-1] = copy.copy(z)

    rev = 0
    a = 0
    for x in t:
        x = ord(x) - ord('a')
        a = nt[a][x]
        if a == 0:
            print((-1))
            return
        if a >= len(s):
            a -= len(s)
            rev += 1
    print((rev*len(s)+a))

if __name__ == '__main__':
    main()
# Original solution
def slove():
    import sys
    import collections
    import bisect
    input = sys.stdin.readline
    s = str(input().rstrip('\n'))
    t = str(input().rstrip('\n'))
    d = collections.defaultdict(list)
    for i in range(len(s)):
        d[s[i]] += [i]

    loop = 0
    pos = 0
    for i in range(len(t)):
        if t[i] not in d:
            print((-1))
            exit()
        else:
            pos = bisect.bisect_left(d[t[i]], pos)
            if len(d[t[i]]) == pos:
                loop += 1
                pos = 0
            pos = d[t[i]][pos] + 1
    print((loop * len(s) + pos))


if __name__ == '__main__':
    slove()


# Optimized solution
import sys
import bisect
import collections


def solve():
    readline = sys.stdin.buffer.readline
    mod = 10 ** 9 + 7
    s = str(readline().rstrip().decode('utf-8'))
    d = collections.defaultdict(list)
    for i in range(len(s)):
        d[s[i]] += [i]
    loop = 0
    pos = 0
    t = str(readline().rstrip().decode('utf-8'))
    for i in range(len(t)):
        if t[i] in d:
            pos = bisect.bisect_left(d[t[i]], pos)
            if pos == len(d[t[i]]):
                loop += 1
                pos = 0
                pos = bisect.bisect_left(d[t[i]], pos)
            pos = d[t[i]][pos] + 1
        else:
            print((-1))
            exit()
    print((loop * len(s) + pos))


if __name__ == '__main__':
    solve()
# Original solution
import sys
sys.setrecursionlimit(10**7)
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def LI_(): return [int(x) - 1 for x in sys.stdin.readline().split()]
def LF(): return [float(x) for x in sys.stdin.readline().split()]
def LS(): return sys.stdin.readline().split()
def II(): return int(sys.stdin.readline())
def SI(): return sys.stdin.readline().strip()
INF = 10 ** 18
MOD = 10 ** 9 + 7

def main(): 
    s = SI()
    t = SI()

    from collections import defaultdict
    s_dict = defaultdict(list)
    for i, char in enumerate(s):
        s_dict[char].append(i)

    # s_dict[char] には、 char が s の何番目に入っているかが記載されている。

    from bisect import bisect, bisect_left

    current_position = 0
    s_loops = 0
    first = True
    for char in t:
        li = s_dict[char]
        if not li:
            print((-1))
            return
        # current_position より大きい最小の要素を二分探索で得る。
        if first:
            first=False
            current_position = li[0]
        else:
            pos = bisect_left(li, current_position)
            try:
                if li[pos] == current_position:
                    current_position = li[pos+1]
                else:
                    current_position = li[pos]
            except IndexError:
                # s は次のループに入った。
                s_loops += 1
                current_position = li[0]
        # print(current_position)
    # if len(set(t)) == 1:
    #     add = 1
    # else:
    add = 1
    print((len(s)*s_loops + current_position+add))


main()

# Optimized solution
import sys
sys.setrecursionlimit(10**7)
def LI(): return [int(x) for x in sys.stdin.readline().split()]
def LI_(): return [int(x) - 1 for x in sys.stdin.readline().split()]
def LF(): return [float(x) for x in sys.stdin.readline().split()]
def LS(): return sys.stdin.readline().split()
def II(): return int(sys.stdin.readline())
def SI(): return sys.stdin.readline().strip()
INF = 10 ** 18
MOD = 10 ** 9 + 7

def main(): 
    s = SI()
    t = SI()

    from collections import defaultdict
    s_dict = defaultdict(list)
    for i, char in enumerate(s):
        s_dict[char].append(i)

    # s_dict[char] には、 char が s の何番目に入っているかが記載されている。

    from bisect import bisect, bisect_left

    current_position = 0
    s_loops = 0
    first = True
    for char in t:
        li = s_dict[char]
        if not li:
            print((-1))
            return
        if first:  # 最初の位置は current_position を信用しないで決める。（そうしないと s,t の1文字目が一致していた場合にひとつ後ろから始めてしまう）
            first = False
            current_position = li[0]
        else:
            # current_position より大きい最小の要素を二分探索で得る。
            # たぶんここで二分探索ができることがオーダーの削減に一役買っていて、このループの計算量が O(len(t) log len(s)) になってる。
            pos = bisect_left(li, current_position)
            try:
                if li[pos] == current_position:
                    current_position = li[pos+1]
                else:
                    current_position = li[pos]
            except IndexError:
                # s は次のループに入った。
                s_loops += 1
                current_position = li[0]

    print((len(s)*s_loops + current_position+1))



main()
# Original solution
import collections
s = input()
t = input()
i = 0
c = 0
while(True):
	progress = False
	j = 0
	for j in range(len(s)):
		if s[j] == t[i]:
			i+=1
			progress = True
			if i == len(t): break
	if progress is False: break
	if i == len(t): break
	c += 1
print(c * len(s) + j + 1 if progress else -1)

# Optimized solution
import collections
s = input()
t = input()
sb = s + s
h = {chr(ord('a') + i):-1 for i in range(26)}
dp = []
for j in range(len(sb)-1,-1,-1):
	dp.append({k:h[k] for k in h})
	h[sb[j]] = j
special = h
dp = dp[::-1]
i = -1
j = 0
c = 0
while(j < len(t)):
	ha = dp[i] if i >= 0 else special
	letter = t[j]
	if ha[letter] != -1:
		i = ha[letter]
		j += 1
	else:
		j = -1
		break

	if i >= len(s):
		i %= len(s)
		c+=1

print((c * len(s) + i + 1) if j != -1 else -1)
# Original solution
import sys
def SI(): return sys.stdin.readline().strip()

def main():
    s = SI()
    t = SI()

    import collections
    didx = collections.defaultdict(int)
    d = collections.defaultdict(list)
    for i, c in enumerate(s):
        d[c].append(i)


    keys = list(d.keys())
    for c in set(t):
        if c not in keys:
            print((-1))
            return

    import bisect

    i_loop = 0
    currentidx = -1
    for c in t:
        # 次の文字を読む
        poslist = d[c]

        if len(poslist) <= didx[c]:
            # 文字を取り切っている場合は次のループに
            i_loop += 1
            didx = collections.defaultdict(int)
            currentidx = poslist[0]
            didx[c] += 1
        else:
            # とり切っていない場合
            poslist_afteridx = poslist[didx[c]:]
            posidx = bisect.bisect_right(poslist_afteridx, currentidx)

            if posidx >= len(poslist_afteridx):
                # とれないなら次のループでとったことにする
                i_loop += 1
                didx = collections.defaultdict(int)
                currentidx = poslist[0]
                didx[c] += 1
            else:
                # 同じループでとれるなら取って、現在位置を更新
                pos = poslist_afteridx[posidx]
                currentidx = pos
                didx[c] = posidx + 1

    print((len(s)*i_loop + currentidx + 1))

main()

# Optimized solution
import sys
def SI(): return sys.stdin.readline().strip()

def main():
    s = SI()
    t = SI()

    import collections
    d = collections.defaultdict(list)
    for i, c in enumerate(s):
        d[c].append(i)

    keys = list(d.keys())
    for c in set(t):
        if c not in keys:
            print((-1))
            return

    import bisect

    i_loop = 0
    currentidx = -1
    for c in t:
        # 次の文字を読む
        poslist = d[c]

        # とり切っていない場合
        posidx = bisect.bisect_right(poslist, currentidx)

        if posidx >= len(poslist):
            # とれないなら次のループでとったことにする
            i_loop += 1
            currentidx = poslist[0]
        else:
            # 同じループでとれるなら取って、現在位置を更新
            pos = poslist[posidx]
            currentidx = pos

    print((len(s)*i_loop + currentidx + 1))

main()
# Original solution
import sys
readline = sys.stdin.readline

S = readline().rstrip()
T = readline().rstrip()

if len(set(T) - set(S)) > 0:
  print((-1))
  exit(0)
  
import bisect
# Tの各文字を探す
S2 = S * 2
from collections import defaultdict
# ある文字が何文字目にあるか辞書
dic = defaultdict(list)

for i in range(len(S2)):
  dic[S2[i]] += [i]

ind = -1
ans = 0
for t in T:
  # 探す文字はt
  targets = dic[t]
#  print("targets",targets,"t",t,"ind + 1",ind + 1)
  newind = targets[bisect.bisect_left(targets, ind + 1)]
#  print("t",t,"S2",S2,"newind",newind)
  ans += (newind - ind)
  if newind >= len(S):
    newind -= len(S)
  ind = newind

print(ans)

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

S = readline().rstrip()
T = readline().rstrip()

if len(set(T) - set(S)) > 0:
  print((-1))
  exit(0)
  
import bisect
S2 = S * 2
from collections import defaultdict
dic = defaultdict(list)

for i in range(len(S2)):
  dic[S2[i]] += [i]

ind = -1
ans = 0
for t in T:
  targets = dic[t]
  newind = targets[bisect.bisect_left(targets, ind + 1)]
  ans += (newind - ind)
  if newind >= len(S):
    newind -= len(S)
  ind = newind

print(ans)
# Original solution
from collections import defaultdict
s=input().strip()
t=input().strip()
def gg(cc, c, l, d):
    if d[c][-1] <= cc:
        return d[c][1], l+1
    ll = d[c]
    mx, mn = len(ll)-2, 0
    x = (mx - mn)//2
    while True:
        if ll[x] <= cc and cc < ll[x+1]:
            return ll[x+1], l
        if cc < ll[x]:
            mx = x
            x = (mx-mn)//2
        else:
            mn = x
            x = (mx-mn)//2

def main():
    ss=set(s)
    tt=set(t)
    if len(tt - ss) != 0: 
        return -1
    d = dict()
    for i, c in enumerate(s):
        if c not in d:
            d[c] = [0]
        d[c].append(i+1)
    cc, l = 0, 0
    for c in t:
        cc, l = gg(cc, c, l, d)
    return l*len(s) + cc

if __name__ == '__main__':
    print((main()))



# Optimized solution
from collections import defaultdict
s=input().strip()
t=input().strip()
def gg(cc, c, l, d):
    if d[c][-1] <= cc:
        return d[c][1], l+1
    ll = d[c]
    mx, mn = len(ll)-1, 0
    x = (mx + mn)//2
    while True:
#        print(x,cc,mx,mn,ll)
        if ll[x] <= cc and cc < ll[x+1]:
            return ll[x+1], l
        if cc < ll[x]:
            mx = x
            x = (mx+mn)//2
        else:
            mn = x
            x = (mx+mn)//2

def main():
    ss=set(s)
    tt=set(t)
    if len(tt - ss) != 0: 
        return -1
    d = dict()
    for i, c in enumerate(s):
        if c not in d:
            d[c] = [0]
        d[c].append(i+1)
    cc, l = 0, 0
    for c in t:
#        print(c)
        cc, l = gg(cc, c, l, d)
    return l*len(s) + cc

if __name__ == '__main__':
    print((main()))
# Original solution
from collections import defaultdict as dd
N, M = list(map(int, input().split()))
c = list(map(int, input().split()))
c.sort()
m = dd(int)
d = dd(int)
for n in c:
  d[n] += 1
  m[n % M] += 1
res = 0
for i in range(M):
  temp = min(m[i], m[(M - i) % M])
  if i == (M - i) % M:
    temp = m[i] // 2
  m[i] -= temp
  m[(M - i) % M] -= temp
  res += temp
for i in range(N):
  n = c[i]
  if m[n % M] > 1:
    k = m[n % M] // 2
    if d[n] > 1:
      temp = min(d[n] // 2, k)
      res += temp
      d[n] -= temp * 2
      m[n % M] -= temp * 2
print(res)

# Optimized solution
import sys
input = sys.stdin.readline
N, M = list(map(int, input().split()))
a = list(map(int, input().split()))
a.sort()
m = [0] * M
d = [0] * (max(a) + 1)
for x in a:
  d[x] += 1
  m[x % M] += 1

res = 0
for i in range(M):
  t = min(m[i], m[(M - i) % M])
  if i == (M - i) % M:
    t = m[i] // 2
  m[i] -= t
  m[(M - i) % M] -= t
  res += t

for i in range(N):
  x = a[i]
  if m[x % M] > 1:
    k = m[x % M] // 2
    if d[x] > 1:
      t = min(d[x] // 2, k)
      res += t
      d[x] -= t * 2
      m[x % M] -= t * 2
print(res)
# Original solution
n,m=list(map(int,input().split()))
a=list(map(int,input().split()))
from collections import Counter
mo=[[]for _ in range(m)]
for i in a:mo[i%m].append(i)
ans=len(mo[0])//2
if m%2==0:ans+=len(mo[m//2])//2
for i in range(1,0--m//2):
  if len(mo[i])>len(mo[m-i]):d=Counter(mo[i])
  elif len(mo[i])==len(mo[m-i]):
    ans+=len(mo[i])
    continue
  else:d=Counter(mo[m-i])
  anss=0
  for j in d:anss+=d[j]//2
  ans+=min(len(mo[i]),len(mo[m-i]))+min(abs(len(mo[i])-len(mo[m-i]))//2,anss)
print(ans)

# Optimized solution
n,m=list(map(int,input().split()))
x=list(map(int,input().split()))
a=[[]for _ in range(m)]
for i in x:a[i%m].append(i)
b=[]
from collections import Counter
for i in range(m):
  d=Counter(a[i])
  ans=0
  for j in d:ans+=2*(d[j]//2)
  b.append([len(a[i]),ans])
ans=0
if m%2==0:ans+=len(a[m//2])//2
ans+=len(a[0])//2
for i in range(1,0--m//2):
  sc,sp=b[i]
  tc,tp=b[m-i]
  v=min(sc,tc)
  ans+=v
  ans+=min(sp,sc-v)//2
  ans+=min(tp,tc-v)//2
print(ans)
# Original solution
from collections import defaultdict, Counter

N, M = list(map(int, input().split()))
X = list(map(int, input().split()))

d = defaultdict(int) #mod Mで見たときの個数
for x in X:
    d[x % M] += 1


ans = 0 #Mの倍数//2 組の和はすべてMの倍数となる
# ans += d[0] // 2

lst = [0] * M
for m in range(1, M):
    ans += min(d[m], d[M - m])
    lst[m] = d[m] - min(d[m], d[M - m]) #mod Mで見たときに残っている個数

ans //= 2
ans += d[0] // 2
# print (ans)
# print ('lst', lst)
# print ('d', d)

C = Counter(X)
for c in C:
    tmp = min(C[c], lst[c % M]) // 2
    lst[c % M] -= 2 * tmp
    ans += tmp

print (ans)






# Optimized solution
#違う数との組-->同じ数での組の順に考える

from collections import defaultdict, Counter

N, M = list(map(int, input().split()))
X = list(map(int, input().split()))

d = defaultdict(int) #mod Mで見たときの個数
for x in X:
    d[x % M] += 1


ans = 0 #Mの倍数//2 組の和はすべてMの倍数となる

lst = [0] * M
for m in range(1, M):
    ans += min(d[m], d[M - m])
    lst[m] = d[m] - min(d[m], d[M - m]) #mod Mで見たときに残っている個数

ans //= 2

ans += d[0] // 2 #0だけは1ダブルカウントしていないのであとから足す

C = Counter(X)
for c in C:
    tmp = min(C[c], lst[c % M]) // 2
    lst[c % M] -= 2 * tmp
    ans += tmp

print (ans)
# Original solution
from collections import Counter

N, M = list(map(int, input().split()))
X = list(map(int, input().split()))

modGrp = [[] for _ in range(M)]

for x in X:
    modGrp[x % M].append(x)

ans = len(modGrp[0]) // 2
modGrp[0] = []

if M % 2 == 0:
    ans += len(modGrp[M // 2]) // 2
    modGrp[M // 2] = []

for m in range(1, M // 2 + 1):
    S = modGrp[m]
    T = modGrp[M - m]

    if len(S) < len(T):
        S, T = T, S

    cnt = Counter(S)
    dis = 0
    for c in list(cnt.values()):
        while c >= 2 and len(S) - dis * 2 > len(T):
            dis += 1
            c -= 2
            ans += 1

    ans += min(len(T), len(S) - dis * 2)
    modGrp[m] = []
    modGrp[M - m] = []

print(ans)

# Optimized solution
from collections import Counter, defaultdict

N, M = list(map(int, input().split()))
X = list(map(int, input().split()))

cntMod = defaultdict(int)
cntDup = defaultdict(int)

for x, c in list(Counter(X).items()):
    cntMod[x % M] += c
    cntDup[x % M] += c // 2

ans = 0
for m in range(M):
    if m > M // 2:
        break
    n = (M - m) % M

    if n == m:
        ans += cntMod[n] // 2
    else:
        mi = min(cntMod[n], cntMod[m])
        ans += mi
        cntMod[n] -= mi
        cntMod[m] -= mi
        ans += min(cntMod[n] // 2, cntDup[n])
        ans += min(cntMod[m] // 2, cntDup[m])

print(ans)
# Original solution
from collections import Counter
N, M = list(map(int, input().split()))
cntX = Counter(list(map(int, input().split())))

cntMod = Counter()
cntDup = Counter()
for x, c in list(cntX.items()):
    cntMod[x % M] += c
    cntDup[x % M] += c // 2

ans = 0
for n in range(M // 2 + 1):
    m = (M - n) % M
    if m == n:
        ans += cntMod[n] // 2
        continue

    cnt = min(cntMod[n], cntMod[m])
    cntMod[n] -= cnt
    cntMod[m] -= cnt

    ans += cnt
    ans += min(cntMod[n] // 2, cntDup[n]) + min(cntMod[m] // 2, cntDup[m])
print(ans)


# Optimized solution
from collections import Counter

N, M = list(map(int, input().split()))
X = list(map(int, input().split()))

dupCnt = Counter()
modCnt = Counter()

for x, c in list(Counter(X).items()):
    x %= M
    dupCnt[x] += c // 2
    modCnt[x] += c

ans = 0
for i in range(M):
    j = M - i
    if i > j:
        break
    if i == j or i == 0:
        ans += modCnt[i] // 2
        continue

    mi = min(modCnt[i], modCnt[j])
    ans += mi

    ans += min((modCnt[i] - mi) // 2, dupCnt[i])
    ans += min((modCnt[j] - mi) // 2, dupCnt[j])

print(ans)