The store sells $n$ beads. The color of each bead is described by a lowercase letter of the English alphabet ("a"–"z"). You want to buy some beads to assemble a necklace from them.

A necklace is a set of beads connected in a circle.

For example, if the store sells beads "a", "b", "c", "a", "c", "c", then you can assemble the following necklaces (these are not all possible options): [Image] 

And the following necklaces cannot be assembled from beads sold in the store: [Image] The first necklace cannot be assembled because it has three beads "a" (of the two available). The second necklace cannot be assembled because it contains a bead "d", which is not sold in the store. 

We call a necklace $k$-beautiful if, when it is turned clockwise by $k$ beads, the necklace remains unchanged. For example, here is a sequence of three turns of a necklace.  [Image]  As you can see, this necklace is, for example, $3$-beautiful, $6$-beautiful, $9$-beautiful, and so on, but it is not $1$-beautiful or $2$-beautiful.

In particular, a necklace of length $1$ is $k$-beautiful for any integer $k$. A necklace that consists of beads of the same color is also beautiful for any $k$.

You are given the integers $n$ and $k$, and also the string $s$ containing $n$ lowercase letters of the English alphabet — each letter defines a bead in the store. You can buy any subset of beads and connect them in any order. Find the maximum length of a $k$-beautiful necklace you can assemble.


-----Input-----

The first line contains a single integer $t$ ($1 \le t \le 100$) — the number of test cases in the test. Then $t$ test cases follow.

The first line of each test case contains two integers $n$ and $k$ ($1 \le n, k \le 2000$).

The second line of each test case contains the string $s$ containing $n$ lowercase English letters — the beads in the store.

It is guaranteed that the sum of $n$ for all test cases does not exceed $2000$.


-----Output-----

Output $t$ answers to the test cases. Each answer is a positive integer — the maximum length of the $k$-beautiful necklace you can assemble.


-----Example-----
Input
6
6 3
abcbac
3 6
aaa
7 1000
abczgyo
5 4
ababa
20 10
aaebdbabdbbddaadaadc
20 5
ecbedececacbcbccbdec

Output
6
3
5
4
15
10



-----Note-----

The first test case is explained in the statement.

In the second test case, a $6$-beautiful necklace can be assembled from all the letters.

In the third test case, a $1000$-beautiful necklace can be assembled, for example, from beads "abzyo".

Difficulty: HARD

Solutions:
t = int(input())
for i in range(t):
	[n, k] = list(map(int, input().split()))
	s = input()
	l = [s.count(a) for a in set(s)]
	M = 0
	for j in range(1, n + 1):
		MM = sum(map(lambda x: x // j, l))
		if MM == 0:
			continue
		while k % MM:
			MM -= 1
		M = max(M, MM * j)
	print(M)


def find(cnt, k, h):
	l = 0
	r = 2001
	while r - l > 1:
		now = 0
		c = (l + r) // 2
		for j in cnt:
			now += j // c
		if now >= h:
			l = c
		else:
			r = c
	return l * h
for i in range(int(input())):
	(n, k) = map(int, input().split())
	cnt = [0] * 26
	for i in input():
		cnt[ord(i) - ord('a')] += 1
	cnt.sort(reverse=True)
	ans = 0
	for i in range(1, k + 1):
		if k % i == 0:
			ans = max(ans, find(cnt, k, i))
			if k // i != i:
				ans = max(ans, find(cnt, k, k // i))
	print(ans)


def good(n, k, letters):
	if letters[-1] >= n:
		return True
	necklace = [-1] * n
	letters_copy = letters[:]
	i = 25
	index = 0
	visited = set()
	while i >= 0:
		indices = set()
		while index not in indices:
			indices.add(index)
			index += k
			index %= n
		if letters_copy[i] >= len(indices):
			letters_copy[i] -= len(indices)
			for j in indices:
				necklace[j] = i
				visited.add(j)
			for j in range(n):
				if j not in visited:
					index = j
					break
		else:
			i -= 1
		if len(visited) == n:
			break
	for j in range(n):
		if necklace[j] == -1:
			return False
		if necklace[j] != necklace[(j + k) % n]:
			return False
	return True

def solve(s, n, k, ans):
	letters = [0] * 26
	for i in s:
		letters[ord(i) - ord('a')] += 1
	letters.sort()
	max_n = 0
	for i in range(1, n + 1):
		if good(i, k, letters):
			max_n = i
	ans.append(max_n)

def main():
	t = int(input())
	ans = []
	for i in range(t):
		(n, k) = map(int, input().split())
		s = input()
		solve(s, n, k, ans)
	for i in ans:
		print(i)
main()


from math import *

def r1(t):
	return t(input())

def r2(t):
	return [t(i) for i in input().split()]

def r3(t):
	return [t(i) for i in input()]
for _ in range(r1(int)):
	(n, k) = r2(int)
	s = r1(str)
	mp = {}
	for i in s:
		mp[i] = 0
	for i in s:
		mp[i] += 1
	t = sorted(mp.values(), reverse=True)
	ans = 1
	for x in range(1, k + 1):
		if k % x == 0:
			y = 1
			while True:
				ta = 0
				for i in t:
					ta += i // y
				if ta < x:
					break
				ans = max(ans, y * x)
				y += 1
	print(ans)


t = int(input())

def gcd(a, b):
	if b == 0:
		return a
	return gcd(b, a % b)
for _ in range(t):
	(n, k) = map(int, input().split())
	s = input()
	occ = [0] * 26
	for i in s:
		occ[ord(i) - 97] += 1
	occ.sort()
	occ.reverse()
	for l in range(1, n + 1):
		cycle = gcd(l, k)
		need = l // cycle
		su = 0
		for i in occ:
			su += i // need
		if su * need >= l:
			wyn = l
	print(wyn)


from collections import deque
import collections

def solve(n, k, s):
	lettersCounter = collections.Counter(s)
	for m in range(n, 0, -1):
		used = [False] * m
		cycles = deque()
		for i in range(m):
			if used[i]:
				continue
			j = (i + k) % m
			used[i] = True
			cycles.insert(len(cycles), 1)
			while not used[j]:
				cycles[len(cycles) - 1] += 1
				used[j] = True
				j = (j + k) % m
		cycles = list(sorted(cycles))
		count = list(sorted(lettersCounter.values()))
		canDoIt = True
		while cycles:
			if count[len(count) - 1] < cycles[len(cycles) - 1]:
				canDoIt = False
				break
			else:
				count[len(count) - 1] -= cycles[len(cycles) - 1]
				cycles.pop()
				count = sorted(count)
		if canDoIt:
			return m
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = input()
	print(solve(n, k, s))


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from math import gcd, ceil

def prod(a, mod=10 ** 9 + 7):
	ans = 1
	for each in a:
		ans = ans * each % mod
	return ans

def lcm(a, b):
	return a * b // gcd(a, b)

def binary(x, length=16):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y
for _ in range(int(input()) if True else 1):
	(n, k) = map(int, input().split())
	s = input()
	count = [0] * 26
	for i in s:
		count[ord(i) - 97] += 1
	count = sorted(count, reverse=True)
	for i in range(n, 0, -1):
		st = set()
		a = []
		for j in range(i):
			jj = j
			count1 = 0
			while jj not in st:
				count1 += 1
				st.add(jj)
				jj = (jj + k) % i
			if count1:
				a += [count1]
		a = sorted(a, reverse=True)
		cc = list(count)
		pos = True
		for each in a:
			f = False
			for ki in range(len(cc)):
				if cc[ki] >= each:
					cc[ki] -= each
					f = True
					break
			if not f:
				pos = False
				break
		if pos:
			print(i)
			break


import sys
input = sys.stdin.readline
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = list(input().rstrip())
	l = []
	for i in range(1, int(k ** 0.5) + 1):
		if k % i == 0:
			if i <= n:
				l.append(i)
			if k // i <= n:
				l.append(k // i)
	l = set(l)
	c = [0] * 26
	for ss in s:
		c[ord(ss) - ord('a')] += 1
	ans = 0
	for kk in l:
		for x in range(1, n + 1):
			can = 0
			for i in range(26):
				can += c[i] // x
			if can > 0 and kk % can == 0:
				ans = max(ans, x * can)
			if can >= kk:
				ans = max(ans, x * kk)
	print(ans)


from collections import Counter
tc = int(input())
while tc:
	(n, k) = map(int, input().split())
	cnt = Counter(input())
	divs = []
	for i in range(1, 1 + int(k ** 0.5)):
		if k % i == 0:
			divs.append(i)
			divs.append(k // i)
	res = 0
	for i in divs:
		rep = 1
		while rep * i <= n:
			c = 0
			for k in cnt:
				c += cnt[k] // rep
			if c >= i:
				res = max(res, rep * i)
			else:
				break
			rep += 1
	print(res)
	tc -= 1


def gcd(a, b):
	if a < b:
		return gcd(b, a)
	if b == 0:
		return a
	return gcd(b, a % b)
for _ in range(int(input())):
	(n, k) = list(map(int, input().split()))
	s = input()
	if s[0] * n == s:
		print(n)
		continue
	cnt = {}
	for c in s:
		if c not in cnt:
			cnt[c] = 0
		cnt[c] += 1
	cnt = [cnt[c] for c in cnt]
	ans = 1
	for x in range(2, n + 1):
		tempK = k % x
		if tempK == 0:
			ans = max(ans, x)
			continue
		mod = x % tempK
		if mod != 0:
			mod = -(mod - tempK)
		times = tempK // gcd(tempK, mod)
		needed = x * times // tempK
		usedBeads = 0
		for num in cnt:
			usedBeads += num - num % needed
		if usedBeads >= x:
			ans = max(ans, x)
	print(ans)


from collections import Counter

def cycleGrouping(length, k):
	groups = [-1 for _ in range(length)]
	currGroupNo = 0
	for i in range(length):
		j = i
		while groups[j] == -1:
			groups[j] = currGroupNo
			j += k
			while j >= length:
				j -= length
		currGroupNo += 1
	groupSizes = list(Counter(groups).values())
	return groupSizes

def checkPossible(freqArr, length, k):
	groupSizes = cycleGrouping(length, k)
	i = 0
	n = len(groupSizes)
	ok = False
	for sz in freqArr:
		while sz >= groupSizes[i]:
			sz -= groupSizes[i]
			i += 1
			if i == n:
				ok = True
				break
		if ok:
			break
	return ok

def main():
	allAns = []
	t = int(input())
	for _ in range(t):
		(n, k) = readIntArr()
		s = input()
		cnts = Counter(s)
		freqArr = list(cnts.values())
		ans = 0
		for length in range(1, n + 1):
			if checkPossible(freqArr, length, k):
				ans = length
		allAns.append(ans)
	multiLineArrayPrint(allAns)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]
main()


from collections import Counter
wer = int(input())
for ewr in range(wer):
	(n, m) = list(map(int, input().split(' ')))
	temp = list(input())
	dic = Counter(temp)
	ans = 1
	for i in range(n, 0, -1):
		t = m % i
		if t == 0:
			ans = i
			break
		else:
			flag = 0
			for k in range(1, t + 1):
				if t % k != 0:
					continue
				te = t // k
				if i % te != 0:
					continue
				else:
					p = i // te
					for j in dic:
						v = dic[j]
						te -= dic[j] // p
					if te < 1:
						flag = 1
						ans = i
						break
			if flag == 1:
				break
	print(ans)


from math import gcd
t = int(input())
for i in range(t):
	(n, k) = map(int, input().split())
	s = input()
	freq = [0 for i in range(26)]
	for _ in s:
		freq[ord(_) - ord('a')] += 1
	freq.sort()
	ans = 1
	for len in range(2, n + 1):
		g = gcd(k, len)
		sz = len // g
		count = 0
		for each in freq:
			count += each // sz
		if count * sz >= len:
			ans = len
	print(ans)


import sys

def minp():
	return sys.stdin.readline().strip()

def mint():
	return int(minp())

def mints():
	return map(int, input().split())

def find(cnt, k, h):
	l = 0
	r = 2001
	while r - l > 1:
		now = 0
		c = (l + r) // 2
		for j in cnt:
			now += j // c
		if now >= h:
			l = c
		else:
			r = c
	return l * h
for i in range(mint()):
	(n, k) = map(int, input().split())
	cnt = [0] * 26
	for i in minp():
		cnt[ord(i) - ord('a')] += 1
	cnt.sort(reverse=True)
	ans = 0
	for i in range(1, k + 1):
		if k % i == 0:
			ans = max(ans, find(cnt, k, i))
			if k // i != i:
				ans = max(ans, find(cnt, k, k // i))
	print(ans)


for _ in range(int(input())):
	(n, k) = map(int, input().split())
	s = input()
	qu = list((0 for i in range(26)))
	qu.sort()
	ans = 0
	for m in range(1, n + 1):
		qu = list((0 for i in range(26)))
		for i in s:
			qu[ord(i) - ord('a')] += 1
		p = list((0 for i in range(m)))
		used = list((False for i in range(m)))
		for i in range(m):
			p[i] = (i + k) % m
		cycle = list()
		for i in range(m):
			if not used[i]:
				h = i
				an = 0
				while not used[h]:
					used[h] = True
					h = p[h]
					an += 1
				cycle.append(an)
		cycle.sort()
		index = 0
		i = 0
		while True:
			if index == 26:
				break
			if i == len(cycle):
				ans = m
				break
			if cycle[i] > qu[index]:
				index += 1
				continue
			qu[index] -= cycle[i]
			i += 1
	print(ans)


import os
import sys
from io import BytesIO, IOBase

def main():
	for _ in range(int(input())):
		(n, k) = map(int, input().split())
		s = input()
		cnt = [0] * 26
		for x in s:
			cnt[ord(x) - ord('a')] += 1
		cnt.sort(reverse=True)

		def chk(n):
			vis = [False] * n
			b = []
			for i in range(n):
				if vis[i]:
					continue
				cur = 0
				while not vis[i]:
					cur += 1
					vis[i] = True
					i = (i + k) % n
				b.append(cur)
			a = []
			for x in cnt:
				if x:
					a.append(x)
				else:
					break
			b.sort(reverse=True)
			for x in b:
				if x > a[0]:
					return False
				a[0] -= x
				a.sort(reverse=True)
			return True
		for l in reversed(range(n + 1)):
			if not chk(l):
				continue
			print(l)
			break
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


from math import gcd

def main():
	(n, k) = map(int, input().split())
	st = input()
	alph = [0 for i in range(ord('z') - ord('a') + 1)]
	for i in st:
		alph[ord(i) - ord('a')] += 1
	for i in range(n, 0, -1):
		n2 = gcd(i, k)
		n1 = i // n2
		for j in alph:
			n2 -= j // n1
		if n2 <= 0:
			print(i)
			return
for t in range(int(input())):
	main()


from functools import cmp_to_key
from collections import deque
from heapq import heappush, heappop
from math import log, ceil
import sys
import os
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()

def inp():
	return sys.stdin.readline().rstrip('\r\n')

def ii():
	return int(inp())

def li(lag=0):
	l = list(map(int, inp().split()))
	if lag != 0:
		for i in range(len(l)):
			l[i] += lag
	return l

def mi(lag=0):
	matrix = list()
	for i in range(n):
		matrix.append(li(lag))
	return matrix

def sli():
	return list(map(str, inp().split()))

def print_list(lista, space=' '):
	print(space.join(map(str, lista)))

class UnionFind:

	def __init__(self, n):
		self.parent = list(range(n))
		self.size = [1] * n
		self.num_sets = n

	def find(self, a):
		to_update = []
		while a != self.parent[a]:
			to_update.append(a)
			a = self.parent[a]
		for b in to_update:
			self.parent[b] = a
		return self.parent[a]

	def merge(self, a, b):
		a = self.find(a)
		b = self.find(b)
		if a == b:
			return
		if self.size[a] < self.size[b]:
			(a, b) = (b, a)
		self.num_sets -= 1
		self.parent[b] = a
		self.size[a] += self.size[b]

	def set_size(self, a):
		return self.size[self.find(a)]

	def __len__(self):
		return self.num_sets

def bisect_left(a, x):
	left = 0
	right = len(a)
	while left < right:
		mid = (left + right) // 2
		if a[mid] < x:
			left = mid + 1
		else:
			right = mid
	return left

def bisect_right(a, x):
	left = 0
	right = len(a)
	while left < right:
		mid = (left + right) // 2
		if a[mid] > x:
			right = mid
		else:
			left = mid + 1
	return left

def bisect_elements(a, x):
	return bisect_right(a, x) - bisect_left(a, x)

def custom_sort(lista):

	def cmp(x, y):
		if x + y > y + x:
			return 1
		else:
			return -1
	return sorted(lista, key=cmp_to_key(cmp))
MOD = 10 ** 9 + 7
maxN = 10 ** 5
FACT = [0] * maxN

def add(x, y):
	return (x + y) % MOD

def multiply(x, y):
	return x * y % MOD

def power(x, y):
	if y == 0:
		return 1
	elif y % 2:
		return multiply(x, power(x, y - 1))
	else:
		a = power(x, y // 2)
		return multiply(a, a)

def inverse(x):
	return power(x, MOD - 2)

def divide(x, y):
	return multiply(x, inverse(y))

def allFactorials():
	FACT[0] = 1
	for i in range(1, maxN):
		FACT[i] = multiply(i, FACT[i - 1])

def coeffBinom(n, k):
	if n < k:
		return 0
	return divide(FACT[n], multiply(FACT[k], FACT[n - k]))

def primes(N):
	smallest_prime = [1] * (N + 1)
	prime = []
	smallest_prime[0] = 0
	smallest_prime[1] = 0
	for i in range(2, N + 1):
		if smallest_prime[i] == 1:
			prime.append(i)
			smallest_prime[i] = i
		j = 0
		while j < len(prime) and i * prime[j] <= N:
			smallest_prime[i * prime[j]] = min(prime[j], smallest_prime[i])
			j += 1
	return (prime, smallest_prime)

def gcd(a, b):
	a = abs(a)
	b = abs(b)
	(s, t, r) = (0, 1, b)
	(old_s, old_t, old_r) = (1, 0, a)
	while r != 0:
		quotient = old_r // r
		(old_r, r) = (r, old_r - quotient * r)
		(old_s, s) = (s, old_s - quotient * s)
		(old_t, t) = (t, old_t - quotient * t)
	return (old_r, old_s, old_t)

def create_graph(n, m, undirected=1, unweighted=1):
	graph = [[] for i in range(n)]
	if unweighted:
		for i in range(m):
			[x, y] = li(lag=-1)
			graph[x].append(y)
			if undirected:
				graph[y].append(x)
	else:
		for i in range(m):
			[x, y, w] = li(lag=-1)
			w += 1
			graph[x].append([y, w])
			if undirected:
				graph[y].append([x, w])
	return graph

def create_tree(n, unweighted=1):
	children = [[] for i in range(n)]
	if unweighted:
		for i in range(n - 1):
			[x, y] = li(lag=-1)
			children[x].append(y)
			children[y].append(x)
	else:
		for i in range(n - 1):
			[x, y, w] = li(lag=-1)
			w += 1
			children[x].append([y, w])
			children[y].append([x, w])
	return children

def create_edges(m, unweighted=0):
	edges = list()
	if unweighted:
		for i in range(m):
			edges.append(li(lag=-1))
	else:
		for i in range(m):
			[x, y, w] = li(lag=-1)
			w += 1
			edges.append([w, x, y])
	return edges

def dist(tree, n, A, B=-1):
	s = [[A, 0]]
	(massimo, massimo_nodo) = (0, 0)
	distanza = -1
	v = [-1] * n
	while s:
		(el, dis) = s.pop()
		if dis > massimo:
			massimo = dis
			massimo_nodo = el
		if el == B:
			distanza = dis
		for child in tree[el]:
			if v[child] == -1:
				v[child] = 1
				s.append([child, dis + 1])
	return (massimo, massimo_nodo, distanza)

def diameter(tree):
	(_, foglia, _) = dist(tree, n, 0)
	(diam, _, _) = dist(tree, n, foglia)
	return diam

def dfs(graph, n, A):
	v = [-1] * n
	s = [[A, 0]]
	v[A] = 0
	while s:
		(el, dis) = s.pop()
		for child in graph[el]:
			if v[child] == -1:
				v[child] = dis + 1
				s.append([child, dis + 1])
	return v

def bfs(graph, n, A):
	v = [-1] * n
	s = deque()
	s.append([A, 0])
	v[A] = 0
	while s:
		(el, dis) = s.popleft()
		for child in graph[el]:
			if v[child] == -1:
				v[child] = dis + 1
				s.append([child, dis + 1])
	return v

def connected(graph, n):
	v = dfs(graph, n, 0)
	for el in v:
		if el == -1:
			return False
	return True

def topological(graph, n):
	indegree = [0] * n
	for el in range(n):
		for child in graph[el]:
			indegree[child] += 1
	s = deque()
	for el in range(n):
		if indegree[el] == 0:
			s.append(el)
	order = []
	while s:
		el = s.popleft()
		order.append(el)
		for child in graph[el]:
			indegree[child] -= 1
			if indegree[child] == 0:
				s.append(child)
	if n == len(order):
		return (False, order)
	else:
		return (True, [])

def bipartite(graph, n):
	color = [-1] * n
	color[0] = 0
	s = [0]
	while s:
		el = s.pop()
		for child in graph[el]:
			if color[child] == color[el]:
				return False
			if color[child] == -1:
				s.append(child)
			color[child] = 1 - color[el]
	return True

def dijkstra(graph, n, A):
	dist = [float('inf') for i in range(n)]
	prev = [-1 for i in range(n)]
	dist[A] = 0
	pq = []
	heappush(pq, [0, A])
	while pq:
		[d_v, v] = heappop(pq)
		if d_v != dist[v]:
			continue
		for (to, w) in graph[v]:
			if dist[v] + w < dist[to]:
				dist[to] = dist[v] + w
				prev[to] = v
				heappush(pq, [dist[to], to])
	return (dist, prev)

def dijkstra_0_1(graph, n, A):
	dist = [float('inf') for i in range(n)]
	dist[A] = 0
	p = deque()
	p.append(A)
	while p:
		v = p.popleft()
		for (to, w) in graph[v]:
			if dist[v] + w < dist[to]:
				dist[to] = dist[v] + w
			if w == 1:
				q.append(to)
			else:
				q.appendleft(to)
	return dist

def floyd_warshall(graph, n):
	dist = [[float('inf') for _ in range(n)] for _ in range(n)]
	for i in range(n):
		dist[i][i] = 0
		for (child, d) in graph[i]:
			dist[i][child] = d
			dist[child][i] = d
	for k in range(n):
		for i in range(n):
			for j in range(j):
				dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
	return dist

def minimum_spanning_tree(edges, n):
	edges = sorted(edges)
	union_find = UnionFind(n)
	used_edges = list()
	for (w, x, y) in edges:
		if union_find.find(x) != union_find.find(y):
			union_find.merge(x, y)
			used_edges.append([w, x, y])
	return used_edges

def parents_children_root_unrooted_tree(tree, n, root=0):
	q = deque()
	visited = [0] * n
	parent = [-1] * n
	children = [[] for i in range(n)]
	q.append(root)
	while q:
		all_done = 1
		visited[q[0]] = 1
		for child in tree[q[0]]:
			if not visited[child]:
				all_done = 0
				q.appendleft(child)
		if all_done:
			for child in tree[q[0]]:
				if parent[child] == -1:
					parent[q[0]] = child
					children[child].append(q[0])
			q.popleft()
	return (parent, children)

def all_longest_path_passing_from_node(parent, children, n):
	q = deque()
	visited = [len(children[i]) for i in range(n)]
	downwards = [[0, 0] for i in range(n)]
	upward = [1] * n
	longest_path = [1] * n
	for i in range(n):
		if not visited[i]:
			q.append(i)
			downwards[i] = [1, 0]
	while q:
		node = q.popleft()
		if parent[node] != -1:
			visited[parent[node]] -= 1
			if not visited[parent[node]]:
				q.append(parent[node])
		else:
			root = node
		for child in children[node]:
			downwards[node] = sorted([downwards[node][0], downwards[node][1], downwards[child][0] + 1], reverse=True)[0:2]
	s = [node]
	while s:
		node = s.pop()
		if parent[node] != -1:
			if downwards[parent[node]][0] == downwards[node][0] + 1:
				upward[node] = 1 + max(upward[parent[node]], downwards[parent[node]][1])
			else:
				upward[node] = 1 + max(upward[parent[node]], downwards[parent[node]][0])
		longest_path[node] = downwards[node][0] + downwards[node][1] + upward[node] - min([downwards[node][0], downwards[node][1], upward[node]]) - 1
		for child in children[node]:
			s.append(child)
	return longest_path

def finding_ancestors(parent, queries, n):
	steps = int(ceil(log(n, 2)))
	ancestors = [[-1 for i in range(n)] for j in range(steps)]
	ancestors[0] = parent
	for i in range(1, steps):
		for node in range(n):
			if ancestors[i - 1][node] != -1:
				ancestors[i][node] = ancestors[i - 1][ancestors[i - 1][node]]
	result = []
	for (node, k) in queries:
		ans = node
		if k >= n:
			ans = -1
		i = 0
		while k > 0 and ans != -1:
			if k % 2:
				ans = ancestors[i][ans]
			k = k // 2
			i += 1
		result.append(ans)
	return result

def prefix_sum(arr):
	r = [0] * (len(arr) + 1)
	for (i, el) in enumerate(arr):
		r[i + 1] = r[i] + el
	return r

def nearest_from_the_left_smaller_elements(arr):
	n = len(arr)
	res = [-1] * n
	s = []
	for (i, el) in enumerate(arr):
		while s and s[-1] >= el:
			s.pop()
		if s:
			res[i] = s[-1]
		s.append(el)
	return res

def sliding_window_minimum(arr, k):
	res = []
	q = deque()
	for (i, el) in enumerate(arr):
		while q and arr[q[-1]] >= el:
			q.pop()
		q.append(i)
		while q and q[0] <= i - k:
			q.popleft()
		if i >= k - 1:
			res.append(arr[q[0]])
	return res

def f(n, k, s):
	c = [0] * 26
	for i in range(n):
		c[ord(s[i]) - ord('a')] += 1
	c = sorted(c, reverse=True)
	k1 = k
	for m in range(n, 0, -1):
		k = k1 % m + (m if k1 % m == 0 else 0)
		s = set()
		for i in range(m):
			s.add(i * k % m)
		l = len(s)
		if l * k % m == 0:
			somma = 0
			for el in c:
				somma += el // l * l
			if somma >= m:
				return m
	return 1
for test in range(ii()):
	(n, k) = li()
	s = str(inp())
	print(f(n, k, s))


from collections import Counter
for _ in range(int(input())):
	(n, k) = map(int, input().split())
	c = Counter(input())
	val = sorted(list(c.values()), reverse=True)
	length = len(val)
	ans = 0
	for i in range(1, k + 1):
		if k % i == 0:
			for l in range(i, n + 1, i):
				temp = 0
				each = l // i
				for j in range(length):
					temp += val[j] // each
				if temp >= i:
					ans = max(ans, l)
				else:
					break
	print(ans)


import math
t = int(input())
for tc in range(t):
	(n, k) = map(int, input().split(' '))
	(s, cnt, an) = (input(), [], 0)
	for i in range(26):
		cnt.append(0)
	for el in s:
		cnt[ord(el) - ord('a')] += 1
	for i in range(1, n + 1):
		gc = math.gcd(i, k)
		(ln, sm) = (i / gc, 0)
		for el in cnt:
			sm += el // ln
		if sm >= gc:
			an = max(an, i)
	print(an)


from math import gcd
from collections import Counter
for _ in range(int(input())):
	(n, k) = [int(j) for j in input().split()]
	s = input()
	(ctr, result) = (Counter(s), 0)
	for i in range(1, n + 1):
		l = i // gcd(i, k)
		cnt = sum([v // l * l for v in ctr.values()])
		if cnt >= i:
			result = i
	print(result)


import math
import collections

def solve(n, k, s):
	ctr = collections.Counter(s)
	for m in range(n, 0, -1):
		g = math.gcd(m, k)
		l = m / g
		count = sum([v // l * l for v in ctr.values()])
		if count >= m:
			print(m)
			break
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = input()
	solve(n, k, s)


import math
from sys import stdin

def factors(n):
	f = []
	f2 = []
	for x in range(1, int(n ** 0.5) + 1):
		if n % x == 0:
			f.append(x)
			f2.append(n // x)
	f2 = f2[::-1]
	if f[-1] == f2[0]:
		f += f2[1:]
	else:
		f += f2
	return f
for case in range(int(stdin.readline())):
	mem = {}
	(n, k) = [int(x) for x in stdin.readline().split()]
	s = stdin.readline().strip()
	chars = {}
	for x in s:
		if x in chars:
			chars[x] += 1
		else:
			chars[x] = 1
	c = []
	for x in chars:
		c.append((chars[x], x))
	c.sort()
	best = c[-1][0]
	for x in range(best + 1, n + 1):
		period = k % x
		if period == 0:
			best = x
		else:
			for y in factors(period):
				if x % y == 0:
					div = x // y
					need = 0
					for (num, l) in c:
						need += num // div
					if need >= y:
						best = x
	print(best)


import math

def modinv(n, p):
	return pow(n, p - 2, p)

def main():
	for case in range(int(input())):
		(n, k) = [int(x) for x in input().split()]
		s = input()
		letters = {}
		for c in s:
			try:
				letters[c] += 1
			except:
				letters[c] = 1
		temp = []
		for key in letters.keys():
			temp.append([letters[key], key])
		temp.sort(reverse=True)
		for l in range(n, 0, -1):
			d = math.gcd(l, k)
			count_per_bead = l // d
			n_beads = d
			c = 0
			for p in temp:
				c += p[0] // count_per_bead
			if c >= n_beads:
				print(l)
				break
py2 = round(0.5)
if py2:
	from future_builtins import ascii, filter, hex, map, oct, zip
	range = xrange
import os, sys
from io import IOBase, BytesIO
BUFSIZE = 8192

class FastIO(BytesIO):
	newlines = 0

	def __init__(self, file):
		self._file = file
		self._fd = file.fileno()
		self.writable = 'x' in file.mode or 'w' in file.mode
		self.write = super(FastIO, self).write if self.writable else None

	def _fill(self):
		s = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
		self.seek((self.tell(), self.seek(0, 2), super(FastIO, self).write(s))[0])
		return s

	def read(self):
		while self._fill():
			pass
		return super(FastIO, self).read()

	def readline(self):
		while self.newlines == 0:
			s = self._fill()
			self.newlines = s.count(b'\n') + (not s)
		self.newlines -= 1
		return super(FastIO, self).readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.getvalue())
			(self.truncate(0), self.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		if py2:
			self.write = self.buffer.write
			self.read = self.buffer.read
			self.readline = self.buffer.readline
		else:
			self.write = lambda s: self.buffer.write(s.encode('ascii'))
			self.read = lambda : self.buffer.read().decode('ascii')
			self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import math
num_tests = int(input())

def calc_num_least(letters, x):
	count = 0
	for letter in letters:
		if letters[letter] >= x:
			count += letters[letter] // x
	return count

def solve(n, k, letters):
	best = 0
	for i in range(1, n + 1):
		j = calc_num_least(letters, i)
		for x in reversed(range(1, j + 1)):
			if k % x == 0:
				best = max(best, x * i)
				break
	return best
for test in range(num_tests):
	(n, k) = [int(x) for x in input().split(' ')]
	s = input()
	letters = {}
	for i in s:
		letters[i] = letters.get(i, 0) + 1
	print(solve(n, k, letters))


t = int(input())
for _ in range(t):
	(n, k) = [int(x) for x in input().split()]
	s = input()
	dict = {}
	ans = 0
	for i in range(len(s)):
		if dict.get(ord(s[i]) - 97) is None:
			dict[ord(s[i]) - 97] = 0
		dict[ord(s[i]) - 97] += 1
	for i in range(1, k + 1):
		if k % i == 0:
			for j in range(i, n + 1, i):
				lol = j // i
				count = 0
				for p in range(26):
					if dict.get(p) is None:
						continue
					count += dict[p] // lol
				if count >= i:
					ans = max(ans, j)
	print(ans)


from sys import stdin
import math
import sys
for _ in range(int(stdin.readline())):
	(N, k) = map(int, stdin.readline().split())
	s = stdin.readline().strip()
	dictt = {}
	for i in s:
		if i not in dictt:
			dictt[i] = 1
		else:
			dictt[i] += 1
	ans = 1
	for n in range(N, 1, -1):
		kt = k % n
		if kt == 0:
			ans = n
			break
		g = math.gcd(n, kt)
		req = n / g
		count = 0
		for i in dictt:
			count += dictt[i] // req
		if count >= g:
			ans = n
			break
	print(ans)


import collections
import time
import os
import sys
import bisect
import heapq
from typing import List

def check(have, m, k):
	if k % m == 0:
		return True
	k %= m
	cycle = [-1 for i in range(m)]
	for i in range(m):
		if cycle[i] < 0:
			(a, b) = (i, (i + k) % m)
			size = 0
			while cycle[a] < 0:
				size += 1
				cycle[a] = b
				(a, b) = (b, (b + k) % m)
			(ti, diff) = (-1, 5000)
			for (hi, hv) in enumerate(have):
				d = hv - size
				if 0 <= d < diff:
					diff = d
					ti = hi
			if ti < 0:
				return False
			have[ti] -= size
	return True

def solve(N, K, S):
	wc = collections.Counter(S)
	have = list(wc.values())
	have.sort(reverse=True)
	ans = 0
	for p in range(1, K + 1):
		if K % p != 0:
			continue
		if p > K:
			break
		for m in range(N, ans, -1):
			if check(have.copy(), m, p):
				ans = max(ans, m)
				break
	return ans
T = int(input())
ans = []
for ti in range(T):
	(N, K) = map(int, input().split())
	S = list(input())
	ans.append(solve(N, K, S))
print('\n'.join(map(str, ans)))


from collections import Counter

def getAllFactors(x):
	factors = []
	for i in range(1, int(x ** 0.5) + 1):
		if x % i == 0:
			factors.append(i)
			if x // i != i:
				factors.append(x // i)
	return sorted(factors)

def checkPossible(nCycles, lastItem, freqArr, k):
	if lastItem >= k:
		return False
	nItemsFilled = 0
	for item in range(lastItem + 1):
		cnt = freqArr[item]
		nItemsFilled += cnt // nCycles
	return nItemsFilled >= k

def getAns(k, freqArr):
	maxCycles = 0
	for lastItem in range(min(k, len(freqArr))):
		b = 2000
		nCycles = 0
		while b > 0:
			while checkPossible(nCycles + b, lastItem, freqArr, k):
				nCycles += b
			b //= 2
		maxCycles = max(maxCycles, nCycles)
	ans = maxCycles * k
	return ans

def main():
	allAns = []
	t = int(input())
	for _ in range(t):
		(n, k) = readIntArr()
		s = input()
		cnts = Counter(s)
		freqArr = list(cnts.values())
		freqArr.sort(reverse=True)
		ans = 0
		factors = getAllFactors(k)
		for f in factors:
			ans = max(ans, getAns(f, freqArr))
		allAns.append(ans)
	multiLineArrayPrint(allAns)
	return
import sys
input = lambda : sys.stdin.readline().rstrip('\r\n')

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]
main()


from collections import Counter
T = int(input())

def possible(m, K, cc):
	answer = 0
	for v in cc:
		answer += v // m
	return answer >= K
for t in range(T):
	(N, K) = [int(_) for _ in input().split()]
	S = input()
	cc = [i[1] for i in Counter(S).most_common()]
	answer = 0
	for k in range(1, K + 1):
		if K % k == 0:
			(l, r) = (1, 2000)
			while l <= r:
				m = (l + r) // 2
				if possible(m, k, cc):
					l = m + 1
					answer = max(answer, m * k)
				else:
					r = m - 1
	print(answer)


import math

def tellFactorsOfK(k):
	sq = int(math.sqrt(k))
	liAns = []
	for i in range(1, sq + 2):
		if k % i == 0:
			liAns.append(i)
			liAns.append(k // i)
	liSet = set()
	liNoDuplicate = []
	for i in liAns:
		if i not in liSet:
			liSet.add(i)
			liNoDuplicate.append(i)
	liNoDuplicate.sort()
	return liNoDuplicate

def isPossibleNecklace(liFreq, size, baseSize):
	multipyBy = size // baseSize
	s = 0
	a = baseSize
	for i in liFreq:
		s += i[1] // multipyBy
		if s >= a:
			return True
	if s >= a:
		return True
	return False

def tellMaxOfOneFactor(liFreq, factor, n):
	ans = -1
	multiplyBy = 1
	while multiplyBy * factor <= n + 1:
		if isPossibleNecklace(liFreq, multiplyBy * factor, factor):
			ans = multiplyBy * factor
		multiplyBy += 1
	return ans
for _ in range(int(input())):
	liStr = input().split()
	n = int(liStr[0])
	k = int(liStr[1])
	s = input()
	liS = list(s)
	diFreq = {}
	for i in s:
		diFreq[i] = diFreq.get(i, 0) + 1
	liFreq = []
	for i in diFreq:
		liTemp = []
		liTemp.append(i)
		liTemp.append(diFreq[i])
		liFreq.append(liTemp)
	liFreq.sort(key=lambda x: x[1], reverse=True)
	liFactorsOfK = tellFactorsOfK(k)
	maxLen = -1
	for factor in liFactorsOfK:
		a = tellMaxOfOneFactor(liFreq, factor, n)
		if a == -1:
			continue
		if a > maxLen:
			maxLen = a
	print(maxLen)


import math
for _ in range(int(input())):
	(n, k) = map(int, input().split())
	st = input()
	dic = {}
	for i in st:
		if i in dic:
			dic[i] += 1
		else:
			dic[i] = 1
	li = list(dic.values())
	li.sort()
	ans = 1
	for i in range(n, 0, -1):
		xx = k % i
		lc = i * xx // math.gcd(i, xx)
		if xx == 0:
			ans = i
			break
		elif lc == i * xx:
			if li[-1] >= i:
				ans = i
				break
		else:
			yy = lc // xx
			count = 0
			for j in li:
				count += j // yy
			if yy * count >= i:
				ans = i
				break
	print(ans)


import sys
inp = [x for x in sys.stdin.read().split()]
ii = 0
ttt = int(inp[ii])
ii += 1
for _ in range(ttt):
	(n, k, s) = (int(inp[ii]), int(inp[ii + 1]), inp[ii + 2])
	ii += 3
	cnt = [0] * 26
	for c in s:
		cnt[ord(c) - ord('a')] += 1
	res = 1
	for d in range(1, k + 1):
		if k % d == 0:
			for l in range(d, n + 1, d):
				q = l // d
				counter = 0
				for x in cnt:
					counter += x // q
				if counter >= d:
					res = max(res, l)
	print(res)


import sys
import math
import heapq
import collections

def inputnum():
	return int(input())

def inputnums():
	return map(int, input().split())

def inputlist():
	return list(map(int, input().split()))

def inputstring():
	return [x for x in input()]

def inputmatrixchar(rows):
	arr2d = [[j for j in input().strip()] for i in range(rows)]
	return arr2d

def inputmatrixint(rows):
	arr2d = []
	for _ in range(rows):
		arr2d.append([int(i) for i in input().split()])
	return arr2d

def computeGCD(x, y):
	while y:
		(x, y) = (y, x % y)
	return x
t = int(input())
for q in range(t):
	(n, k) = inputnums()
	s = inputstring()
	d = {}
	for i in range(n):
		if s[i] not in d:
			d[s[i]] = 1
		else:
			d[s[i]] += 1
	for i in reversed(range(1, n + 1)):
		t = i / computeGCD(i, k)
		cnt = 0
		for key in d:
			cnt += d[key] // t
		if cnt * t >= i:
			print(i)
			break


import math
test = int(input())
for t in range(0, test):
	(n, k) = map(int, input().split())
	s = input()
	count = [0 for i in range(0, 26)]
	for ch in s:
		count[ord(ch) - ord('a')] += 1
	count.sort()
	fin = 1
	for m in range(2, n + 1):
		c = math.gcd(m, k)
		d = m // c
		ans = 0
		for x in count:
			ans += x // d
		if ans * d >= m:
			fin = m
	print(fin)


import math
from collections import defaultdict

def getDivisors(n):
	i = 1
	ans = []
	while i <= math.sqrt(n):
		if n % i == 0:
			if n / i == i:
				ans.append(i)
			else:
				ans.append(i)
				ans.append(n // i)
		i = i + 1
	return ans
t = int(input())
while t != 0:
	(n, k) = map(int, input().split())
	s = str(input())
	maxx = 0
	freq = defaultdict(int)
	for i in range(n):
		freq[s[i]] += 1
	fact = getDivisors(k)
	for lenn in fact:
		for l in range(lenn, n + 1, lenn):
			possible = 0
			each = l // lenn
			for f in freq.values():
				possible += f // each
			if possible >= lenn:
				maxx = max(maxx, l)
			else:
				break
	print(maxx)
	t -= 1


import math
from collections import Counter

def main(n, k, s):
	cnt = Counter(s)
	for l in range(n, 0, -1):
		t = l / math.gcd(l, k)
		s = sum((v // t * t for v in cnt.values()))
		if s >= l:
			return l
for _ in range(int(input())):
	print(main(*map(int, input().split()), input()))


from collections import defaultdict
for _ in range(int(input())):
	(n, k) = list(map(int, input().split()))
	s = input()
	mp = [0 for i in range(26)]
	for i in s:
		mp[ord(i) - ord('a')] += 1
	mp.sort()
	mp = mp[-1::-1]
	ans = 0
	for i in range(1, n + 1):
		m = i
		cnt = 0
		temp = [-1 for i in range(m)]
		for j in range(m):
			if temp[j] == -1:
				ind = j
				while True:
					if temp[ind] != -1:
						break
					temp[ind] = cnt
					ind += k
					ind = ind % m
				cnt += 1
			else:
				temp[(j + k) % m] = temp[j]
		freq = [0 for j in range(max(temp) + 1)]
		for j in temp:
			freq[j] += 1
		freq.sort()
		freq = freq[-1::-1]
		overall = mp[:]
		for j in freq:
			f = 0
			for p in range(len(overall)):
				if j <= overall[p]:
					overall[p] -= j
					f = 1
					break
			if f == 0:
				break
		if f == 1:
			ans = max(ans, i)
	print(ans)


def check(x):
	add = 0
	for i in range(26):
		add += alpha[i] // x
	return add

def gcd(a, b):
	if b == 0:
		return a
	return gcd(b, a % b)
for t in range(int(input())):
	(n, m) = map(int, input().split())
	alpha = [0 for i in range(26)]
	st = input()
	for i in range(n):
		alpha[ord(st[i]) - 97] += 1
	maxi = 0
	for i in range(1, n + 1):
		if i <= m:
			if m % i == 0:
				j = 1
				maxi = max(maxi, i)
				while True:
					q = check(j)
					if q < i:
						break
					maxi = max(maxi, i * j)
					j += 1
		else:
			r = gcd(i, m)
			if r >= 1:
				s = max(m, i) // r
				p = check(s)
				if p >= r:
					maxi = max(maxi, i)
	print(maxi)


from math import *
for _ in range(int(input())):
	(n, k) = [int(i) for i in input().split()]
	s = input()
	dic = dict()
	for i in s:
		dic[i] = 0
	for i in s:
		dic[i] += 1
	t = sorted(dic.values(), reverse=True)
	r = 1
	for x in range(1, k + 1):
		if k % x == 0:
			y = 1
			while True:
				ta = 0
				for i in t:
					ta += i // y
				if ta < x:
					break
				r = max(r, y * x)
				y += 1
	print(r)


rr = lambda : input().strip()
rri = lambda : int(rr())
rrm = lambda : [int(x) for x in rr().split()]
from sys import stdin, stdout

def sol():
	(n, k) = rrm()
	s = input().strip()
	fr = [0 for i in range(26)]
	for c in s:
		fr[ord(c) - ord('a')] += 1
	res = 1
	for i in range(1, k + 1):
		if k % i == 0:
			x = 1
			while True:
				cn = x * i
				z = 0
				for j in fr:
					z += j // x
				if z < i:
					break
				x += 1
			x -= 1
			res = max(res, x * i)
	print(res)
	return
T = rri()
for t in range(1, T + 1):
	ans = sol()


def possible(n, brr, k):
	chk = []
	visited = [0] * n
	for i in range(n):
		cnt = 0
		if visited[i] == 0:
			visited[i] = 1
			j = (i + k) % n
			cnt += 1
			while j != i:
				visited[j] = 1
				cnt += 1
				j = (j + k) % n
		chk.append(cnt)
	i = 0
	j = 0
	while i < len(chk) and j < len(brr):
		if chk[i] <= brr[j]:
			brr[j] -= chk[i]
			i += 1
		else:
			j += 1
	if i != len(chk):
		return False
	return True
t = int(input())
for i in range(t):
	(n, k) = map(int, input().split())
	s = input()
	d = dict()
	for i in s:
		d[i] = d.get(i, 0) + 1
	arr = list(d.values())
	arr.sort(reverse=True)
	ans = -1
	for i in range(n, 0, -1):
		brr = arr.copy()
		if possible(i, brr, k):
			ans = i
			break
	print(ans)


import os
inp = os.read(0, int(10000000.0)).split()
inp_pos = -1

def cin():
	global inp_pos
	inp_pos += 1
	return inp[inp_pos]
from itertools import groupby
from math import gcd
T = int(cin())
res = []
while T:
	T -= 1
	n = int(cin())
	k = int(cin())
	a = [len(list(g)) for (k, g) in groupby(sorted(cin()))]
	ans = 0
	for v in range(1, n + 1):
		d = gcd(v, k)
		f = v // d
		if sum([x // f for x in a]) >= d:
			ans = v
	res.append(str(ans).encode())
os.write(1, '\n'.encode().join(res))


import math
for _ in range(int(input())):
	(n, k) = map(int, input().split())
	s = input()
	count = [0] * 26
	for ch in s:
		count[ord(ch) - ord('a')] += 1
	count.sort()
	res = 1
	for i in range(2, n + 1):
		g = math.gcd(i, k)
		l = i // g
		ans = 0
		for x in count:
			ans += x // l
		if ans * l >= i:
			res = i
	print(res)


import heapq

def maxheappush(x, xx):
	heapq.heapify(x)
	heapq.heappush(x, -1 * xx)

def maxheappop(x):
	heapq.heapify(x)
	ans = -1 * heapq.heappop(x)
	return ans

class Graph:

	def __init__(self, V):
		self.V = V
		self.adj = [[] for i in range(V)]

	def DFSUtil(self, temp, v, visited):
		visited[v] = True
		temp.append(v)
		for i in self.adj[v]:
			if visited[i] == False:
				temp = self.DFSUtil(temp, i, visited)
		return temp

	def addEdge(self, v, w):
		self.adj[v].append(w)
		self.adj[w].append(v)

	def connectedComponents(self):
		visited = []
		cc = []
		for i in range(self.V):
			visited.append(False)
		for v in range(self.V):
			if visited[v] == False:
				temp = []
				cc.append(self.DFSUtil(temp, v, visited))
		return cc

def returncount(l):
	dic = {}
	for ss in range(len(l)):
		if l[ss] not in dic:
			dic[l[ss]] = 1
		else:
			dic[l[ss]] += 1
	val = list(dic.values())
	val = sorted(val, reverse=True)
	return val

def modlist(x, k):
	vals = []
	it = 1
	g = Graph(x)
	for i in range(x):
		g.addEdge(i, (i + k) % x)
	cc = g.connectedComponents()
	for c in cc:
		vals.append(len(c))
	vals = sorted(vals, reverse=True)
	return vals

def findfeas(b, s):
	c = []
	heapq.heapify(c)
	for bb in b:
		maxheappush(c, bb)
	ans = maxheappop(c)
	while ans >= s[0]:
		ans = ans - s[0]
		s.pop(0)
		maxheappush(c, ans)
		ans = maxheappop(c)
		if len(s) == 0:
			break
	if len(s) == 0:
		return True
	else:
		return False
t = int(input())
for i in range(t):
	(n, k) = [int(x) for x in input().split(' ')]
	s = input()
	rc = returncount(s)
	for j in range(n, 0, -1):
		gg = modlist(j, k)
		if findfeas(rc, gg):
			print(j)
			break


from collections import *
import math
a = int(input())
for i in range(a):
	(n, k) = map(int, input().split())
	s = input()
	al = defaultdict(int)
	for i in range(len(s)):
		al[s[i]] += 1
	ans = []
	for i in al:
		ans.append(al[i])
	maxa = 0
	for i in range(1, n + 1):
		rem = k % i
		if rem == 0:
			maxa = max(maxa, i)
		else:
			q = i // math.gcd(rem, i)
			c1 = 0
			for x in range(len(ans)):
				c1 += ans[x] // q
			if c1 >= i // q:
				maxa = max(maxa, i)
	print(maxa)


from sys import stdin
from collections import deque
mod = 10 ** 9 + 7
import sys
import random
from queue import PriorityQueue
from collections import Counter as cc
from bisect import bisect_right
from bisect import bisect_left
from collections import defaultdict
from math import sqrt, factorial, gcd, log2, inf, ceil
import heapq
input = lambda : sys.stdin.readline().rstrip()
from sys import stdin, stdout
from heapq import heapify, heappush, heappop
from itertools import permutations
from math import factorial as f

def ncr(n, r, p):
	num = den = 1
	for i in range(r):
		num = num * (n - i) % p
		den = den * (i + 1) % p
	return num * pow(den, p - 2, p) % p
import sys
import sys
from math import gcd
input = sys.stdin.readline
from collections import Counter as cc
I = lambda : list(map(int, input().split()))
(t,) = I()
for _ in range(t):
	(n, k) = I()
	s = list(input().strip())
	l = cc(s)
	a = list(l.values())
	for i in range(n, 0, -1):
		g = gcd(i, k)
		p = i // g
		an = 0
		for j in a:
			if j >= p:
				an += j // p * p
		if an >= i:
			print(i)
			break


import math
from collections import defaultdict
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = input()
	d = defaultdict(int)
	for i in s:
		d[i] += 1
	freq = []
	for i in d:
		freq.append(d[i])
	freq.sort(reverse=True)
	for l in range(n, 0, -1):
		if k % l == 0:
			ans = l
			break
		else:
			size_of_window = int(math.gcd(l, k))
			no_of_windows = l // size_of_window
			ele_in_one_window = 0
			for i in freq:
				ele_in_one_window += i // no_of_windows
			if ele_in_one_window >= size_of_window:
				ans = l
				break
	print(ans)


import math
import sys
input = sys.stdin.readline
for _ in range(int(input())):
	(n, k) = map(int, input().split())
	s = input().strip()
	ans = 0
	i = 1
	d = [0] * 26
	for z in s:
		d[ord(z) - ord('a')] += 1
	while i * i <= k:
		if k % i == 0:
			_i = i
			for __ in range(2):
				for x in range(1, n + 1):
					sum = 0
					for j in d:
						sum += j // x
					if sum >= _i:
						ans = max(ans, x * _i)
				_i = k // i
		i += 1
	print(ans)


t = int(input())
while t:
	(n, k) = [int(i) for i in input().split()]
	s = input()
	mem = {i: 0 for i in s}
	for c in s:
		mem[c] += 1
	chars = sorted(list(mem.values()))
	for i in range(n, 0, -1):
		p = [-1] * i
		for j in range(i):
			p[j] = (j + k) % i
		cycles = []
		unused = set([x for x in range(i)])
		while unused:
			curr = unused.pop()
			unused.add(curr)
			l = 0
			while curr in unused:
				l += 1
				unused.remove(curr)
				curr = p[curr]
			cycles.append(l)
		cycles.sort()
		x = 0
		y = 0
		char_counts = chars.copy()
		while x < len(cycles) and y < len(char_counts):
			if char_counts[y] >= cycles[x]:
				char_counts[y] -= cycles[x]
				x += 1
				if char_counts[y] != 0:
					y -= 1
			y += 1
		if x >= len(cycles):
			print(i)
			break
	t -= 1


import math
import collections
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = input()
	ctr = collections.Counter(s)
	ans = 0
	for i in range(1, n + 1):
		g = math.gcd(i, k)
		l = i // g
		cnt = sum([v // l * l for v in ctr.values()])
		if cnt >= i:
			ans = i
	print(ans)


def gcd(a, b):
	return gcd(b, a % b) if b else a
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = input()
	elements = {}
	for i in s:
		if i in elements.keys():
			elements[i] += 1
		else:
			elements[i] = 1
	for i in range(n, 0, -1):
		every_nth = gcd(k, i)
		can_give = 0
		for j in elements.keys():
			can_give += elements[j] // (i // every_nth)
		if can_give >= every_nth:
			print(i)
			break


import sys
from collections import Counter
from math import gcd

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(input())

def MAP():
	return 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')
INF = 10 ** 19
MOD = 10 ** 9 + 7
for _ in range(INT()):
	(N, K) = MAP()
	S = input()
	C = Counter(S)
	ans = 0
	for ln in range(1, N + 1):
		cnt = 0
		x = ln // gcd(ln, K)
		for v in C.values():
			cnt += v // x * x
		if cnt >= ln:
			ans = max(ans, ln)
	print(ans)


import sys
from math import gcd
input = sys.stdin.readline
from collections import Counter as cc
I = lambda : list(map(int, input().split()))
(t,) = I()
for _ in range(t):
	(n, k) = I()
	s = list(input().strip())
	l = cc(s)
	a = list(l.values())
	for i in range(n, 0, -1):
		g = gcd(i, k)
		p = i // g
		an = 0
		for j in a:
			if j >= p:
				an += j // p * p
		if an >= i:
			print(i)
			break


def gcd(a, b):
	if b == 0:
		return a
	else:
		return gcd(b, a % b)
t = int(input())
for test in range(0, t):
	(n, k) = input().split()
	n = int(n)
	k = int(k)
	s = input()
	dic = {}
	b = []
	for i in range(0, n):
		if s[i] in dic:
			b[dic[s[i]]] += 1
		else:
			dic[s[i]] = len(b)
			b.append(1)
	kk = k
	b.sort()
	for l in range(n, 0, -1):
		k = kk % l
		if k == 0:
			print(l)
			break
		s = k * l // gcd(l, k) // k
		ll = l
		for i in range(len(b) - 1, -1, -1):
			ll -= b[i] // s * s
			if ll <= 0:
				print(l)
				break
		if ll <= 0:
			break


def HOD(a, b):
	while a != 0 and b != 0:
		if a > b:
			a %= b
		else:
			b %= a
	return a + b
for _ in range(int(input())):
	(n, k) = map(int, input().split())
	s = list(input())
	d = {}
	for i in s:
		if i not in d:
			d[i] = 1
		else:
			d[i] += 1
	a = sorted(d.values())[::-1]
	for i in range(n, 0, -1):
		x = k % i
		if x == 0:
			break
		types = HOD(i, x)
		same = i // types
		c = 0
		for j in a:
			c += j // same
		if c >= types:
			break
	print(i)


import sys
from collections import defaultdict as dd
from collections import Counter as cc
from queue import Queue
import math
import itertools
try:
	sys.stdin = open('input.txt', 'r')
	sys.stdout = open('output.txt', 'w')
except:
	pass
for _ in range(int(input())):
	(n, k) = map(int, input().split())
	a = input()
	r = sorted(list(cc(a).values()))
	for i in range(n, 0, -1):
		q = math.gcd(i, k)
		w = i // q
		z = 0
		for j in r:
			if j >= w:
				z += j // w * w
		if z >= i:
			print(i)
			break


from math import gcd
from collections import Counter
for _ in range(int(input())):
	(n, k) = map(int, input().split())
	cou = Counter(input())
	factors = [[1] for _ in range(2001)]
	for i in range(2, 2001):
		x = i
		while x <= 2000:
			factors[x].append(i)
			x += i
	maxi = 0
	for i in range(1, n + 1):
		pe = factors[gcd(i, k)]
		ans = [0] * len(pe)
		for (j, y) in enumerate(pe):
			for x in cou:
				if cou[x] >= i // y:
					ans[j] += cou[x] // (i // y)
			if ans[j] >= y:
				maxi = i
	print(maxi)


from math import sqrt
from collections import defaultdict as dd
import sys
input = sys.stdin.readline
t = int(input())
while t:
	d = dd(int)
	(n, k) = map(int, input().split())
	s = input().split()[0]
	for i in s:
		d[i] += 1
		pre = [0] * (n + 1)
	for i in range(1, n + 1):
		for j in d:
			pre[i] += d[j] // i
	factors = []
	for i in range(1, int(sqrt(k)) + 1):
		if k % i == 0:
			factors.append(i)
			if i != k // i:
				factors.append(k // i)
	mx = 0
	for i in factors:
		for j in range(1, n + 1):
			if pre[j] >= i:
				mx = max(mx, i * j)
	print(mx)
	t -= 1


from sys import stdout, stdin
input = stdin.readline
for t in range(int(input())):
	(n, k) = map(int, input().split())
	s = input().strip()
	a = [0 for i in range(26)]
	for i in s:
		a[ord(i) - 97] += 1
	x = 0
	for i in a:
		if i == n:
			x = i
			break
	if x != 0:
		stdout.write(str(n) + '\n')
		continue
	for z in range(n, -1, -1):
		q = a[:]
		visited = [0 for i in range(z)]
		cycle = []
		for i in range(z):
			if visited[i] == 0:
				j = i
				l = 0
				while visited[j] == 0:
					visited[j] = 1
					j = (j + k) % z
					l += 1
				cycle.append(l)
		flag = 0
		for i in cycle:
			flag = 0
			for j in range(26):
				if q[j] >= i:
					flag = 1
					q[j] = q[j] - i
					break
			if flag == 0:
				break
		if flag == 1:
			stdout.write(str(z) + '\n')
			break


PI = 3.141592653589793
INF = float('inf')
MOD = 1000000007

def add(x, y):
	return (x + y) % MOD

def sub(x, y):
	return (x - y + MOD) % MOD

def mul(x, y):
	return x * y % MOD

def gcd(x, y):
	if y == 0:
		return x
	return gcd(y, x % y)

def lcm(x, y):
	return x * y // gcd(x, y)

def power(x, y):
	res = 1
	x %= MOD
	while y != 0:
		if y & 1:
			res = mul(res, x)
		y >>= 1
		x = mul(x, x)
	return res

def mod_inv(n):
	return power(n, MOD - 2)

def prob(p, q):
	return mul(p, power(q, MOD - 2))

def ii():
	return int(input())

def li():
	return [int(i) for i in input().split()]

def ls():
	return [i for i in input().split()]

def fun():
	for i in vis:
		if i == -1:
			return 1
	return 0
for t in range(ii()):
	t += 1
	(n, k) = li()
	s = input()
	f = [0 for i in range(26)]
	store = []
	for i in s:
		f[ord(i) - 97] += 1
	for i in f:
		store.append(i)
	store.sort()
	store.reverse()
	ans = 1
	for i in range(2, n + 1):
		x = k % i
		if x == 0:
			ans = i
		else:
			need = i // gcd(i, x)
			cnt = 0
			for j in store:
				d = j // need
				cnt += d * need
			if cnt >= i:
				ans = i
	print(ans)


from collections import defaultdict as dd
from collections import deque
import bisect
import heapq

def ri():
	return int(input())

def rl():
	return list(map(int, input().split()))

def gcd(a, b):
	while b:
		(a, b) = (b, a % b)
	return a

def solve():
	(n, k) = rl()
	s = input()
	counts = dd(int)
	for c in s:
		counts[c] += 1
	amts = sorted(counts.values(), reverse=True)

	def check(l):
		shift = k % l
		if shift == 0:
			return True
		groups = gcd(l, shift)
		size = l // groups
		hits = 0
		for val in amts:
			if val >= size:
				hits += val // size
				if hits >= groups:
					return True
			else:
				break
		return False
	for l in range(n, 0, -1):
		if check(l):
			print(l)
			break
mode = 'T'
if mode == 'T':
	t = ri()
	for i in range(t):
		solve()
else:
	solve()


import io
import os
from bisect import bisect
from collections import Counter
from math import gcd

def divisors(n):
	front = []
	back = []
	for x in range(1, int(n ** 0.5) + 1):
		if n % x == 0:
			front.append(x)
			back.append(n // x)
	if front[-1] == back[0]:
		front.pop()
	return front + back[::-1]

def firstSmaller(arr, x):
	index = bisect(arr, x)
	if index == 0:
		assert False
	assert arr[index - 1] <= x
	return arr[index - 1]

def solve(N, K, S):
	divs = divisors(K)
	freq = Counter(S)
	best = 1
	for repeat in range(max(freq.values()), 0, -1):
		pattern = []
		for (k, v) in freq.items():
			pattern.extend([k] * (v // repeat))
		trunc = firstSmaller(divs, len(pattern))
		print('pattern', pattern[:trunc] * repeat)
		best = max(best, trunc * repeat)
	return best

def solve(N, K, S):
	freq = Counter(S)
	for n in range(N, 0, -1):
		patternLen = gcd(K, n)
		repeat = n // patternLen
		possibleLen = 0
		for (k, v) in freq.items():
			possibleLen += v // repeat
		if possibleLen >= patternLen:
			return n
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
T = int(input())
for t in range(T):
	(N, K) = [int(x) for x in input().split()]
	S = input().decode().rstrip()
	ans = solve(N, K, S)
	print(ans)


import math
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = list(input())
	l = [0] * 26
	for i in s:
		l[ord(i) - ord('a')] += 1
	for i in range(n, 0, -1):
		x = math.gcd(i, k)
		p = i // x
		count = 0
		for j in l:
			if j >= p:
				count += j // p * p
		if count >= i:
			print(i)
			break


from collections import Counter

def gcd(a, b):
	if b > a:
		return gcd(b, a)
	if b == 0:
		return a
	else:
		return gcd(b, a % b)
t = int(input())
for _ in range(t):
	(n, k) = list(map(int, input().split()))
	s = input()
	x = Counter(s)
	for i in range(1, n + 1):
		g = gcd(i, k)
		l = i // g
		cnt = sum([v // l * l for v in x.values()])
		if cnt >= i:
			ans = i
	print(ans)


from __future__ import division, print_function
import os
import sys
from io import BytesIO, IOBase
import datetime
if sys.version_info[0] < 3:
	from __builtin__ import xrange as range
	from future_builtins import ascii, filter, hex, map, oct, zip

def main():
	starttime = datetime.datetime.now()
	tc = int(input())
	for _ in range(tc):
		(n, k) = [int(x) for x in input().split()]
		s = input()
		d = {}
		for i in s:
			if i not in d:
				d[i] = 1
			else:
				d[i] += 1
		sd = {k: v for (k, v) in sorted(d.items(), key=lambda item: item[1], reverse=True)}
		fa = []
		for i in sd:
			fa.append(sd[i])
		ans = 0
		for i in range(n, 0, -1):
			vis = [0] * i
			size = []
			sc = 0
			for j in range(i):
				c = 1
				t = j
				if vis[j] == 0:
					vis[j] = 1
					while True:
						if vis[(j + k) % i] == 1:
							break
						else:
							vis[(j + k) % i] = 1
							j = (j + k) % i
							c += 1
					sc += c
					size.append(c)
				j = t
				if sc >= i:
					break
			if len(set(size)) == 1:
				u = 0
				flag = 0
				z = fa[0]
				for e in size:
					if z - e < 0:
						u += 1
						if u == len(fa):
							flag = 1
							break
						z = fa[u]
					z -= e
				if flag == 0 and z >= 0:
					ans = sc
					print(ans)
					break
			if ans > 0:
				break
	endtime = datetime.datetime.now()
	time = (endtime - starttime).total_seconds() * 1000
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

def print(*args, **kwargs):
	(sep, file) = (kwargs.pop('sep', ' '), kwargs.pop('file', sys.stdout))
	at_start = True
	for x in args:
		if not at_start:
			file.write(sep)
		file.write(str(x))
		at_start = False
	file.write(kwargs.pop('end', '\n'))
	if kwargs.pop('flush', False):
		file.flush()
if sys.version_info[0] < 3:
	(sys.stdin, sys.stdout) = (FastIO(sys.stdin), FastIO(sys.stdout))
else:
	(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import sys
import io, os
input = sys.stdin.readline
from functools import reduce

def factors(n):
	x = set(reduce(list.__add__, ([i, n // i] for i in range(1, int(n ** 0.5) + 1) if n % i == 0)))
	return list(x)

def checker(mid):
	count = []
	for i in range(n, 0, -1):
		ans = 0
		for j in alpha:
			if j >= i:
				ans += j // i
				if ans >= mid:
					return mid * i // mid * mid
	return 0
t = int(input())
for ii in range(t):
	(n, k) = map(int, input().split())
	s = [i for i in input() if i != '\n']
	alpha = [0] * 26
	for i in s:
		alpha[ord(i) - 97] += 1
	l = factors(k)
	ans = []
	for i in l:
		ans.append(checker(i))
	print(max(ans))


import math
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = input()
	countLetters = [0] * 26
	for elem in s:
		countLetters[ord(elem) - ord('a')] += 1
	factors = []
	for i in range(1, int(math.sqrt(k)) + 1):
		if k % i == 0:
			factors.append(i)
			factors.append(k // i)
	groups = []
	for i in range(1, n + 1):
		sumBeads = 0
		for elem in countLetters:
			sumBeads += elem // i
		groups.append(sumBeads)
	maxNecklace = 0
	for elem in factors:
		maxGroup = 0
		for i in range(n):
			if groups[i] < elem:
				break
			else:
				maxGroup = i + 1
		if maxNecklace < maxGroup * elem:
			maxNecklace = maxGroup * elem
	print(maxNecklace)


import sys
from collections import Counter, deque
T = int(input())
for _ in range(T):
	(n, k) = map(int, input().split())
	cc = Counter(input())
	cc = list(sorted(cc.values(), reverse=True))
	mx = cc[0]
	for d in range(2, k + 1):
		if k % d:
			continue
		for u in range(1, n // d + 1):
			cnt = 0
			for v in cc:
				if v // u == 0:
					break
				cnt += v // u
			if cnt >= d:
				mx = max(mx, d * u)
	print(mx)


letters = 26
for t in range(int(input())):
	(n, k) = map(int, input().split(' '))
	s = input()
	counts = [0] * (letters + 1)
	for c in s:
		counts[ord(c) - ord('a')] += 1
	counts.sort(reverse=True)
	zeroi = counts.index(0)
	if zeroi >= 0:
		counts = counts[:zeroi]
	ans = 1
	for d in range(1, min(k, n) + 1):
		if k % d != 0:
			continue
		l = 1
		r = n // d
		while l < r:
			m = (l + r + 1) // 2
			inGroup = 0
			for count in counts:
				inGroup += count // m
			if inGroup >= d:
				l = m
			else:
				r = m - 1
		ans = max(ans, l * d)
	print(ans)


def gcd(n, k):
	if n % k == 0:
		return k
	return gcd(k, n % k)
t = int(input())
for you in range(t):
	l = input().split()
	n = int(l[0])
	k = int(l[1])
	s = input()
	freq = [0 for i in range(26)]
	for i in s:
		freq[ord(i) - 97] += 1
	mina = []
	for i in range(1, n + 1):
		x = gcd(i, k)
		sumi = 0
		for j in range(26):
			sumi = sumi + freq[j] // (i // x)
		if sumi >= x:
			mina.append(i)
	print(max(mina))


import collections
import string

def main():
	(n, k) = map(int, input().split())
	s = input()
	c = collections.Counter(s)
	cnt = sorted(list(c.values()))
	divs = []
	i = 1
	while i * i < k:
		if k % i == 0:
			divs.append(i)
			divs.append(k // i)
		i += 1
	if i * i == k:
		divs.append(i)
	divs.sort()
	while divs[-1] > n:
		divs.pop()
	ans = cnt[-1]
	for period in divs:
		l = 0
		r = (n + period) // period
		while l + 1 < r:
			m = (l + r) // 2
			chunks = 0
			for i in range(-min(period, len(cnt)), 0):
				chunks += cnt[i] // m
			if chunks >= period:
				l = m
			else:
				r = m
		cycles = l
		ans = max(ans, cycles * period)
	print(ans)
tn = int(input())
for _ in range(tn):
	main()


def gcd(a, b):
	return a if b == 0 else gcd(b, a % b)

def feasible(n, k, beads, lng, maxcnt):
	g = gcd(k, lng)
	h = lng // g
	if g == 1:
		return lng <= maxcnt
	g0 = 0
	for (_, c) in beads.items():
		g0 += c // h
	return g <= g0

def solve(n, k, beads):
	maxcnt = 0
	for (_, c) in beads.items():
		if c > maxcnt:
			maxcnt = c
	for lng in range(n, 1, -1):
		if feasible(n, k, beads, lng, maxcnt):
			return lng
	return 1
cases = int(input().strip())
for _ in range(cases):
	(n, k) = tuple(map(int, input().strip().split()))
	store = input().strip()
	beads = {}
	for b in store:
		if b in beads:
			beads[b] += 1
		else:
			beads[b] = 1
	print(solve(n, k, beads))


from collections import Counter
import bisect
for _ in range(int(input())):
	(n, k) = [int(j) for j in input().split()]
	s = input()
	c = Counter(s)
	l = sorted([c[i] for i in c])[::-1]
	d = []
	for i in range(1, k + 1):
		if k % i == 0:
			d.append(i)
	ans = 0
	for i in d:
		for j in range(i, n + 1, i):
			c = 0
			for k in l:
				if k >= j // i:
					c += k // (j // i)
				else:
					break
			if c >= i:
				ans = max(j, ans)
			else:
				break
	print(ans)


import sys, math, os
from bisect import bisect_left as bl, bisect_right as br, insort
from heapq import heapify, heappush, heappop
from collections import defaultdict as dd, deque, Counter
from decimal import Decimal
from fractions import Fraction

def data():
	return sys.stdin.readline().strip()

def mdata():
	return list(map(int, data().split()))

def outl(var):
	sys.stdout.write(' '.join(map(str, var)) + '\n')

def out(var):
	sys.stdout.write(str(var) + '\n')
INF = 10 ** 20
mod = 10 ** 9 + 7
for t in range(int(data())):
	(n, k) = mdata()
	s = data()
	d = dd(int)
	for i in range(n):
		d[s[i]] += 1
	l = sorted(d.values(), reverse=True)
	ans = 0
	div = []
	for i in range(1, int(k ** 0.5) + 1):
		if k % i == 0:
			div.append(i)
			div.append(k // i)
	for i in range(1, n + 1):
		cnt = 0
		for j in l:
			cnt += j // i
		for j in div:
			if cnt >= j:
				ans = max(ans, j * i)
	out(ans)


import heapq
from collections import Counter
from sys import stdin
input = stdin.readline
INF = 10 ** 9 + 7
MAX = 10 ** 7 + 7
MOD = 10 ** 9 + 7

def check(n, k, c):
	h = list(c)
	heapq.heapify(h)
	v = [0] * n
	for ni in range(n):
		if v[ni]:
			continue
		if not h:
			return False
		nj = ni
		(freq, char) = heapq.heappop(h)
		cnt = 0
		while not v[nj]:
			v[nj] = 1
			nj += k
			nj %= n
			cnt += 1
		if -freq > cnt:
			heapq.heappush(h, [freq + cnt, char])
		elif -freq < cnt:
			return False
	return True
for Ti in range(int(input().strip())):
	(n, k) = [int(x) for x in input().strip().split()]
	s = input().strip()
	c = [[-x[1], x[0]] for x in list(Counter(s).items())]
	for i in range(n, 0, -1):
		if check(i, k, c):
			print(i)
			break


def make_divisors(n):
	(lower_divisors, upper_divisors) = ([], [])
	i = 1
	while i * i <= n:
		if n % i == 0:
			lower_divisors.append(i)
			if i != n // i:
				upper_divisors.append(n // i)
		i += 1
	return lower_divisors + upper_divisors[::-1]

def main():
	q = int(input())
	for _ in range(q):
		(n, k) = map(int, input().split())
		s = input()
		while n > 0:
			if k % n == 0:
				ans = n
				break
			n -= 1
		alphabet = [0] * 26
		n = len(s)
		for i in range(n):
			alphabet[ord(s[i]) - 97] += 1
		KL = make_divisors(k)
		for nk in KL:
			ok = 0
			ng = pow(10, 18)

			def check(x, k):
				if x == 0:
					return True
				if k * x > n:
					return False
				val = 0
				for num in alphabet:
					temp = num // x * x
					val += temp
				if val >= x * k:
					return True
				else:
					return False
			while abs(ok - ng) > 1:
				mid = (ok + ng) // 2
				if check(mid, nk):
					ok = mid
				else:
					ng = mid
			ans = max(ans, ok * nk)
		print(ans)
main()


import sys
input = sys.stdin.readline
import math
import copy
import bisect
import collections
from collections import deque
import heapq
from collections import defaultdict
t = int(input())
for f in range(t):
	(n, k) = map(int, input().split())
	div = []
	for i in range(1, 2001):
		if k % i == 0:
			div.append(i)
	s = list(input().rstrip())
	c = collections.Counter(s)
	a = c.most_common()
	freq = []
	for i in a:
		freq.append(i[1])
	ans = 0
	for i in div:
		j = 1
		tmp = 0
		while j * i <= n:
			memo = 0
			for l in range(len(freq)):
				memo += freq[l] // j
			if memo >= i:
				tmp = j * i
				j += 1
			else:
				break
		ans = max(ans, tmp)
	print(ans)


import math
import random
import heapq, bisect
import sys
from collections import deque, defaultdict
from fractions import Fraction
import sys
import threading
from collections import defaultdict
mod = 10 ** 9 + 7
mod1 = 998244353
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

class TreeNode:

	def __init__(self, k, v):
		self.key = k
		self.value = v
		self.left = None
		self.right = None
		self.parent = None
		self.height = 1
		self.num_left = 1
		self.num_total = 1

class AvlTree:

	def __init__(self):
		self._tree = None

	def add(self, k, v):
		if not self._tree:
			self._tree = TreeNode(k, v)
			return
		node = self._add(k, v)
		if node:
			self._rebalance(node)

	def _add(self, k, v):
		node = self._tree
		while node:
			if k < node.key:
				if node.left:
					node = node.left
				else:
					node.left = TreeNode(k, v)
					node.left.parent = node
					return node.left
			elif node.key < k:
				if node.right:
					node = node.right
				else:
					node.right = TreeNode(k, v)
					node.right.parent = node
					return node.right
			else:
				node.value = v
				return

	@staticmethod
	def get_height(x):
		return x.height if x else 0

	@staticmethod
	def get_num_total(x):
		return x.num_total if x else 0

	def _rebalance(self, node):
		n = node
		while n:
			lh = self.get_height(n.left)
			rh = self.get_height(n.right)
			n.height = max(lh, rh) + 1
			balance_factor = lh - rh
			n.num_total = 1 + self.get_num_total(n.left) + self.get_num_total(n.right)
			n.num_left = 1 + self.get_num_total(n.left)
			if balance_factor > 1:
				if self.get_height(n.left.left) < self.get_height(n.left.right):
					self._rotate_left(n.left)
				self._rotate_right(n)
			elif balance_factor < -1:
				if self.get_height(n.right.right) < self.get_height(n.right.left):
					self._rotate_right(n.right)
				self._rotate_left(n)
			else:
				n = n.parent

	def _remove_one(self, node):
		replacement = node.left or node.right
		if node.parent:
			if AvlTree._is_left(node):
				node.parent.left = replacement
			else:
				node.parent.right = replacement
			replacement.parent = node.parent
			node.parent = None
		else:
			self._tree = replacement
			replacement.parent = None
		node.left = None
		node.right = None
		node.parent = None
		self._rebalance(replacement)

	def _remove_leaf(self, node):
		if node.parent:
			if AvlTree._is_left(node):
				node.parent.left = None
			else:
				node.parent.right = None
			self._rebalance(node.parent)
		else:
			self._tree = None
		node.parent = None
		node.left = None
		node.right = None

	def remove(self, k):
		node = self._get_node(k)
		if not node:
			return
		if AvlTree._is_leaf(node):
			self._remove_leaf(node)
			return
		if node.left and node.right:
			nxt = AvlTree._get_next(node)
			node.key = nxt.key
			node.value = nxt.value
			if self._is_leaf(nxt):
				self._remove_leaf(nxt)
			else:
				self._remove_one(nxt)
			self._rebalance(node)
		else:
			self._remove_one(node)

	def get(self, k):
		node = self._get_node(k)
		return node.value if node else -1

	def _get_node(self, k):
		if not self._tree:
			return None
		node = self._tree
		while node:
			if k < node.key:
				node = node.left
			elif node.key < k:
				node = node.right
			else:
				return node
		return None

	def get_at(self, pos):
		x = pos + 1
		node = self._tree
		while node:
			if x < node.num_left:
				node = node.left
			elif node.num_left < x:
				x -= node.num_left
				node = node.right
			else:
				return (node.key, node.value)
		raise IndexError('Out of ranges')

	@staticmethod
	def _is_left(node):
		return node.parent.left and node.parent.left == node

	@staticmethod
	def _is_leaf(node):
		return node.left is None and node.right is None

	def _rotate_right(self, node):
		if not node.parent:
			self._tree = node.left
			node.left.parent = None
		elif AvlTree._is_left(node):
			node.parent.left = node.left
			node.left.parent = node.parent
		else:
			node.parent.right = node.left
			node.left.parent = node.parent
		bk = node.left.right
		node.left.right = node
		node.parent = node.left
		node.left = bk
		if bk:
			bk.parent = node
		node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
		node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
		node.num_left = 1 + self.get_num_total(node.left)

	def _rotate_left(self, node):
		if not node.parent:
			self._tree = node.right
			node.right.parent = None
		elif AvlTree._is_left(node):
			node.parent.left = node.right
			node.right.parent = node.parent
		else:
			node.parent.right = node.right
			node.right.parent = node.parent
		bk = node.right.left
		node.right.left = node
		node.parent = node.right
		node.right = bk
		if bk:
			bk.parent = node
		node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
		node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
		node.num_left = 1 + self.get_num_total(node.left)

	@staticmethod
	def _get_next(node):
		if not node.right:
			return node.parent
		n = node.right
		while n.left:
			n = n.left
		return n

class SegmentTree1:

	def __init__(self, data, default=0, func=lambda a, b: max(a, b)):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class SegmentTree:

	def __init__(self, data, default=0, func=lambda a, b: a + b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class Factorial:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorials = [1, 1]
		self.invModulos = [0, 1]
		self.invFactorial_ = [1, 1]

	def calc(self, n):
		if n <= -1:
			print('Invalid argument to calculate n!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.factorials):
			return self.factorials[n]
		nextArr = [0] * (n + 1 - len(self.factorials))
		initialI = len(self.factorials)
		prev = self.factorials[-1]
		m = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * i % m
		self.factorials += nextArr
		return self.factorials[n]

	def inv(self, n):
		if n <= -1:
			print('Invalid argument to calculate n^(-1)')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		p = self.MOD
		pi = n % p
		if pi < len(self.invModulos):
			return self.invModulos[pi]
		nextArr = [0] * (n + 1 - len(self.invModulos))
		initialI = len(self.invModulos)
		for i in range(initialI, min(p, n + 1)):
			next = -self.invModulos[p % i] * (p // i) % p
			self.invModulos.append(next)
		return self.invModulos[pi]

	def invFactorial(self, n):
		if n <= -1:
			print('Invalid argument to calculate (n^(-1))!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.invFactorial_):
			return self.invFactorial_[n]
		self.inv(n)
		nextArr = [0] * (n + 1 - len(self.invFactorial_))
		initialI = len(self.invFactorial_)
		prev = self.invFactorial_[-1]
		p = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * self.invModulos[i % p] % p
		self.invFactorial_ += nextArr
		return self.invFactorial_[n]

class Combination:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorial = Factorial(MOD)

	def ncr(self, n, k):
		if k < 0 or n < k:
			return 0
		k = min(k, n - k)
		f = self.factorial
		return f.calc(n) * f.invFactorial(max(n - k, k)) * f.invFactorial(min(k, n - k)) % self.MOD

def powm(a, n, m):
	if a == 1 or n == 0:
		return 1
	if n % 2 == 0:
		s = powm(a, n // 2, m)
		return s * s % m
	else:
		return a * powm(a, n - 1, m) % m

def sort_list(list1, list2):
	zipped_pairs = zip(list2, list1)
	z = [x for (_, x) in sorted(zipped_pairs)]
	return z

def product(l):
	por = 1
	for i in range(len(l)):
		por *= l[i]
	return por

def binarySearchCount(arr, n, key):
	left = 0
	right = n - 1
	count = 0
	while left <= right:
		mid = int((right + left) / 2)
		if arr[mid] < key:
			count = mid + 1
			left = mid + 1
		else:
			right = mid - 1
	return count

def countdig(n):
	c = 0
	while n > 0:
		n //= 10
		c += 1
	return c

def binary(x, length):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y

def countGreater(arr, n, k):
	l = 0
	r = n - 1
	leftGreater = n
	while l <= r:
		m = int(l + (r - l) / 2)
		if arr[m] >= k:
			leftGreater = m
			r = m - 1
		else:
			l = m + 1
	return n - leftGreater
for ik in range(int(input())):
	(n, k) = map(int, input().split())
	s = input()
	d = defaultdict(int)
	for i in range(n):
		d[s[i]] += 1
	d = list(d.values())
	d.sort(reverse=True)
	d1 = d + []
	for i in range(n, 0, -1):
		d = d1 + []
		graph = defaultdict(set)
		vis = [False] * (n + 1)
		req = []

		def dfs(v):
			vis[v] = True
			c = 1
			for i in graph[v]:
				if vis[i] == False:
					c += dfs(i)
			return c
		for j in range(1, i + 1):
			if (j + k) % i == j:
				continue
			if (j + k) % i == 0:
				graph[j].add((j + k) % i + i)
				graph[(j + k) % i + i].add(j)
			else:
				graph[j].add((j + k) % i)
				graph[(j + k) % i].add(j)
		for j in range(1, i + 1):
			if vis[i] == False:
				req.append(dfs(j))
		req.sort(reverse=True)
		f = 0
		t = 0
		for j in range(len(req)):
			if d[t] >= req[j]:
				d[t] -= req[j]
			else:
				f = 0
				while d[t] < req[j]:
					t += 1
					if t == len(d):
						f = 1
						break
				if f == 1:
					break
				d[t] -= req[j]
		if f == 0:
			print(i)
			break


import sys
import math
from math import factorial, inf, gcd, sqrt
from heapq import *
from functools import *
from itertools import *
from collections import *
from typing import *
from bisect import *
import random
sys.setrecursionlimit(10 ** 5)

def rarray():
	return [int(i) for i in input().split()]
t = 1
t = int(input())
for ii in range(t):
	(n, k) = rarray()
	s = input()
	v = sorted(Counter(s).values(), reverse=True)
	for ans in reversed(range(1, n + 1)):
		g = gcd(ans, k)
		p = ans // g
		r = 0
		cv = v.copy()
		while g > 0:
			f = True
			for (i, j) in enumerate(cv):
				if j >= p:
					cv[i] -= p
					g -= 1
					f = False
				if g == 0:
					break
			if f:
				break
		if g == 0:
			print(ans)
			break


from sys import stdin, stdout

def necklace_assembly(n, k, s):
	res = 0
	cna = [0 for i in range(26)]
	for i in range(len(s)):
		cna[ord(s[i]) - ord('a')] += 1
	for i in range(n, 0, -1):
		l = k % i
		if l == 0:
			res = i
			break
		g = gcd(i, l)
		if g != 0:
			d = 0
			need = i // g
			for v in cna:
				d += v // need * need
			if d >= i:
				res = i
				break
	return res

def gcd(a, b):
	if b == 0:
		return a
	return gcd(b, a % b)
t = int(stdin.readline())
for i in range(t):
	(n, k) = list(map(int, stdin.readline().split()))
	s = stdin.readline().strip()
	stdout.write(str(necklace_assembly(n, k, s)) + '\n')


import math
T = int(input())
for _ in range(T):
	(n, k) = map(int, input().split())
	a = [0] * 26
	for i in input().strip():
		a[ord(i) - ord('a')] += 1
	x = n
	while sum((i - i % (x // math.gcd(x, k)) for i in a)) < x:
		x -= 1
	print(x)


import math

def f(n):
	c = []
	d = []
	i = 1
	while i <= math.sqrt(n):
		if n % i == 0:
			if n // i == i:
				c.append(i)
			else:
				c.append(i)
				d.append(n // i)
		i += 1
	c += d[::-1]
	return c
t = int(input())
for i in range(t):
	(n, k) = map(int, input().split())
	s = input()
	b = f(k)
	ans = 0
	c = [0] * 26
	for j in range(n):
		c[ord(s[j]) - 97] += 1
	k = []
	for j in range(26):
		p = c[j]
		i = 1
		while p // i != 0:
			k.append(p // i)
			i += 1
	k.sort(reverse=True)
	j = 0
	r = len(k)
	while j < len(b):
		p = b[j]
		if p - 1 < r:
			ans = max(ans, p * k[p - 1])
		j += 1
	print(ans)


from os import path
import sys
from functools import cmp_to_key as ctk
from collections import deque, defaultdict as dd
from bisect import bisect, bisect_left, bisect_right, insort, insort_left, insort_right
from itertools import permutations
from datetime import datetime
from math import ceil, sqrt, log, gcd

def ii():
	return int(input())

def si():
	return input()

def mi():
	return map(int, input().split())

def li():
	return list(mi())
abc = 'abcdefghijklmnopqrstuvwxyz'
abd = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g': 6, 'h': 7, 'i': 8, 'j': 9, 'k': 10, 'l': 11, 'm': 12, 'n': 13, 'o': 14, 'p': 15, 'q': 16, 'r': 17, 's': 18, 't': 19, 'u': 20, 'v': 21, 'w': 22, 'x': 23, 'y': 24, 'z': 25}
mod = 1000000007
inf = float('inf')
vow = ['a', 'e', 'i', 'o', 'u']
(dx, dy) = ([-1, 1, 0, 0], [0, 0, 1, -1])

def bo(i):
	return ord(i) - ord('a')

def solve():
	for _ in range(ii()):
		(n, k) = mi()
		s = si()
		f = [0] * 26
		for i in s:
			f[bo(i)] += 1
		ans = 0
		for i in range(1, n + 1):
			req = gcd(i, k)
			cnt = i // req
			c = 0
			for j in range(26):
				req -= f[j] // cnt
			if req <= 0:
				ans = i
		print(ans)
solve()


def solve(N, k, s):
	count = [0] * 26
	for c in s:
		count[ord(c) - 97] += 1
	ans = 0
	for n in range(1, N + 1):
		X = 0
		for c in count:
			X += c // n
		for x in range(X, 0, -1):
			if k % x == 0:
				ans = max(ans, x * n)
				break
	return ans
t = int(input())
for _ in range(t):
	(n, k) = input().split()
	(n, k) = (int(n), int(k))
	s = input()
	print(solve(n, k, s))


from collections import Counter
from math import gcd, floor, sqrt
for _ in range(int(input())):
	(n, k) = map(int, input().split())
	s = input().strip()
	z = sorted(list(Counter(s).values()), reverse=True)
	ma = max(z)
	an = 0
	for x in range(1, k + 1):
		if k % x == 0:
			for xx in range(1, n // x + 1):
				s = 0
				for j in range(len(z)):
					s += z[j] // xx
				if s >= x:
					an = max(x * xx, an)
	print(an)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from math import factorial
from collections import Counter, defaultdict, deque
from heapq import heapify, heappop, heappush

def RL():
	return map(int, sys.stdin.readline().rstrip().split())

def RLL():
	return list(map(int, sys.stdin.readline().rstrip().split()))

def N():
	return int(input())

def comb(n, m):
	return factorial(n) / (factorial(m) * factorial(n - m)) if n >= m else 0

def perm(n, m):
	return factorial(n) // factorial(n - m) if n >= m else 0

def mdis(x1, y1, x2, y2):
	return abs(x1 - x2) + abs(y1 - y2)
mod = 998244353
INF = float('inf')

def main():
	for _ in range(N()):
		(n, k) = RL()
		s = list(input())
		rec = [0] * 26
		for i in s:
			rec[ord(i) - ord('a')] += 1
		res = 1
		for d in range(1, k + 1):
			if k % d == 0:
				for l in range(d, n + 1, d):
					ct = 0
					time = l // d
					for num in rec:
						ct += num // time
					if ct >= d:
						res = max(res, l)
		print(res)
main()


import os
import sys
from io import BytesIO, IOBase
import heapq as h
from bisect import bisect_left, bisect_right
from types import GeneratorType
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		import os
		self.os = os
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = self.os.read(self._fd, max(self.os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			self.os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
from collections import defaultdict as dd, deque as dq, Counter as dc
import math, string

def getInts():
	return [int(s) for s in input().split()]

def getInt():
	return int(input())

def getStrs():
	return [s for s in input().split()]

def getStr():
	return input()

def listStr():
	return list(input())
MOD = 998244353
from functools import reduce

def factors(n):
	return set(reduce(list.__add__, ([i, n // i] for i in range(1, int(n ** 0.5) + 1) if n % i == 0)))

def solve():
	(N, K) = getInts()
	S = getStr()
	lets = [0] * 26
	for s in S:
		lets[ord(s) - ord('a')] += 1
	lets.sort()
	facs = factors(K)
	best = 0
	for f in facs:
		curr = 1
		while True:
			tmp = [L // curr for L in lets]
			if sum(tmp) < f:
				curr -= 1
				break
			curr += 1
		best = max(best, curr * f)
	return best
for _ in range(getInt()):
	print(solve())


for i in range(int(input())):
	(n, k) = list(map(int, input().split()))
	s = input()
	a = [0] * 26
	for i in s:
		a['abcdefghijklmnopqrstuvwxyz'.find(i)] += 1
	z = 1
	a = sorted(a)[::-1]
	a0 = list(a)
	for i in range(1, n + 1):
		b = []
		c = [0] * i
		d = 0
		for j in range(i):
			if c[j] == 0:
				d += 1
				b.append(1)
				c[j] = d
				j0 = j
				j = (j - k) % i
				while j != j0:
					b[-1] += 1
					c[j] = d
					j = (j - k) % i
		for j in b:
			for l in range(26):
				if a[l] >= j:
					a[l] -= j
					break
			else:
				break
		else:
			z = i
		a = list(a0)
	print(z)


from sys import stdout, stdin
import os, io
input = stdin.readline

def read_int():
	return map(int, input().split())

def read_list():
	return list(map(int, input().split()))

def print_list(l):
	print(' '.join(map(str, l)))
from collections import Counter

def gcd(m, n):
	while n:
		(m, n) = (n, m % n)
	return m
N = int(input())
for _ in range(N):
	(n, k) = read_int()
	bead = input().strip()
	dic = Counter(bead)
	for i in range(n, 0, -1):
		target = gcd(i, k)
		m = i // target
		tmp = 0
		for d in dic.values():
			tmp += d // m
			if tmp >= target:
				break
		if tmp >= target:
			print(i)
			break


import sys
from array import array
import typing as Tp

def input():
	return sys.stdin.buffer.readline().decode('utf-8')

def main():
	from collections import Counter
	from math import gcd
	t = int(input())
	ans_a = [0] * t
	for ti in range(t):
		(n, k) = map(int, input().split())
		char_cnt = list(Counter(input().rstrip()).values())
		if k == 0:
			ans_a[ti] = n
			continue
		for i in range(n, 0, -1):
			group = gcd(k, i)
			cnt = i // group
			if sum((x // cnt for x in char_cnt)) >= group:
				ans_a[ti] = i
				break
	sys.stdout.buffer.write(('\n'.join(map(str, ans_a)) + '\n').encode('utf-8'))
main()


import sys
import math
import collections
input = sys.stdin.readline

def main():
	t = int(input())
	for _ in range(t):
		(N, K) = [int(x) for x in input().split()]
		S = input().strip()
		c = collections.Counter(S)
		for i in range(N + 1, -1, -1):
			ik_gcd = math.gcd(i, K)
			x = i // ik_gcd
			tmpcnt = 0
			for k in c.keys():
				tmpcnt += c[k] // x
			if tmpcnt >= ik_gcd:
				print(i)
				break
main()


import sys
import math as mt

def divisors(n):
	l = []
	i = 1
	while i <= mt.sqrt(n):
		if n % i == 0:
			if n // i == i:
				l.append(i)
			else:
				l.append(i)
				l.append(n // i)
		i = i + 1
	return l
t = int(input())
for __ in range(t):
	(n, k) = map(int, input().split())
	s = input()
	l = [0] * 27
	for i in range(len(s)):
		l[ord(s[i]) - 97] += 1
	l.sort()
	maxi = 1
	for i in range(n, 0, -1):
		l1 = divisors(i)
		for j in l1:
			g = mt.gcd(j, k)
			ch = 0
			same = i // g
			cnt = 0
			for i1 in range(len(l)):
				if l[i1] >= same:
					cnt += l[i1] // same
			if cnt >= g:
				maxi = max(maxi, i)
	print(maxi)


from math import gcd
from collections import Counter
for _ in range(int(input())):
	(n, k) = map(int, input().split())
	cou = Counter(input())
	maxi = 0
	for i in range(1, n + 1):
		pe = gcd(i, k)
		ans = 0
		for x in cou:
			if cou[x] >= i // pe:
				ans += cou[x] // (i // pe)
		if ans >= pe:
			maxi = i
	print(maxi)


from collections import Counter
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = input()
	cc = [v for (_, v) in Counter(s).items()]
	cc.sort()
	mx = 0
	for subk in range(1, k + 1):
		if k % subk != 0:
			continue
		for l in range(1, n + 1):
			local = sum(map(lambda x: x // l, cc))
			if local >= subk:
				mx = max(mx, subk * l)
	print(mx)


T = int(input())

def solve():
	[N, K] = list(map(int, input().split()))
	count = {}
	S = input()
	for c in S:
		if c not in count:
			count[c] = 0
		count[c] += 1

	def necklace_size(m):
		count_ = count.copy()
		ans = [None for _ in range(m)]
		for i in range(len(ans)):
			if ans[i] != None:
				continue
			cyclic_group = set()
			j = i
			while j not in cyclic_group:
				cyclic_group.add(j)
				j += K
				j %= m
			key = None
			val = -1
			for k in count_:
				if count_[k] >= len(cyclic_group):
					if key == None:
						key = k
						val = count_[k]
					elif count_[k] < val:
						key = k
						val = count_[k]
			if key == None:
				return False
			for i in cyclic_group:
				ans[i] = key
				count_[key] -= 1
		return ''.join(ans)
	for i in range(len(S), -1, -1):
		foo = necklace_size(i)
		if foo:
			return len(foo)
	return -1
for _ in range(T):
	print(solve())


from collections import Counter
from math import gcd

def solve(s: str, k: int) -> int:
	c = Counter(s).values()
	best = 0
	for length in range(1, len(s) + 1):
		period = gcd(length, k)
		min_count = length // period
		current = 0
		for v in c:
			current += v // min_count
			if current >= period:
				best = length
				break
	return best
tc = int(input())
while tc > 0:
	(n, k) = map(int, input().split())
	print(solve(input(), k))
	tc -= 1


from collections import Counter
from collections import defaultdict
from collections import deque
import math
import heapq
import sys
import io, os
input = sys.stdin.readline
from bisect import *
rs = lambda : input().strip()
ri = lambda : int(input())
rl = lambda : list(map(int, input().strip().split()))
rls = lambda : list(map(str, input().split()))
t = int(input())
for _ in range(0, t):
	(n, k) = rl()
	s = input()
	d = Counter(s)
	v = list(d.values())
	x1 = sorted(v, reverse=True)
	v.sort(reverse=True)
	for i in range(n, 0, -1):
		vis = [0] * i
		l = []
		for j in range(0, i):
			if vis[j] == 1:
				continue
			c = j
			a = 0
			while 1:
				if vis[c] == 1:
					l.append(a)
					break
				vis[c] = 1
				a = a + 1
				c = (c + k) % i
		p = 0
		f = 1
		v = x1.copy()
		for j in l:
			while 1:
				if p == len(v):
					f = 0
					break
				if v[p] >= j:
					v[p] = v[p] - j
					break
				else:
					p = p + 1
		if f == 1:
			print(i)
			break


def main():
	t = int(input())
	for _ in range(t):
		(n, k) = map(int, input().split())
		s = input()
		d = {}
		M = 0
		for i in s:
			if i in d:
				d[i] += 1
			else:
				d[i] = 1
			M = max(M, d[i])
		s = sorted(d.keys(), key=lambda x: d[x], reverse=True)
		qs = [k]
		for j in range(2, int(k ** 0.5) + 2):
			if k % j == 0:
				qs.append(j)
				qs.append(k // j)
		L = M
		for q in qs:
			max_reps = n // q
			for reps in range(max_reps, 0, -1):
				total_contribs = 0
				for potential_contributor in s:
					given_contrib = d[potential_contributor] // reps
					if given_contrib == 0:
						break
					total_contribs += given_contrib
				if total_contribs < q:
					continue
				L = max(L, q * reps)
				break
		print(L)
main()


import math

def factors(a):
	i = 1
	x = math.sqrt(a)
	lis = []
	while i <= x:
		if a % i == 0:
			if i == x:
				lis.append(i)
			else:
				lis.append(i)
				lis.append(a // i)
		i += 1
	lis.sort()
	return lis
t = int(input())
for i in range(t):
	(n, k) = list(map(int, input().split()))
	s = str(input())
	array = factors(k)
	lis = [0] * 26
	for j in range(n):
		lis[ord(s[j]) - 97] += 1
	arr = []
	for j in range(26):
		if lis[j] > 0:
			arr.append(lis[j])
	ans = 0
	for j in array:
		l = j
		while l <= n:
			s = 0
			x = l // j
			for m in arr:
				s += m // x
			if s >= j:
				ans = max(ans, l)
			l += j
	print(ans)


import collections
import math
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = input()
	cnt = list((i for (j, i) in collections.Counter(s).items()))
	for i in range(n, 0, -1):
		l = math.gcd(k, i)
		r = i // l
		for j in cnt:
			l -= j // r
		if l <= 0:
			break
	print(i)


from math import gcd
from sys import stdin, gettrace
from collections import Counter
if gettrace():
	inputi = input
else:

	def input():
		return next(stdin)[:-1]

	def inputi():
		return stdin.buffer.readline()

def main():

	def solve(n, k, ss):
		(_, counts) = zip(*Counter(ss).most_common())
		for i in range(n, 0, -1):
			if k % i == 0:
				return i
			j = gcd(k, i)
			l = i // j
			found = 0
			for c in counts[0:j]:
				found += c // l
			if found >= j:
				return i
	t = int(inputi())
	for _ in range(t):
		(n, k) = map(int, input().split())
		ss = list(input())
		print(solve(n, k, ss))
main()


import sys
input = sys.stdin.readline
RI = lambda : [int(x) for x in sys.stdin.readline().strip().split()]
rw = lambda : input().strip().split()
from collections import defaultdict as df
t = int(input().strip())
for _ in range(t):
	(n, k) = RI()
	s = input().strip()
	d = df(int)
	for i in s:
		d[i] += 1
	for i in range(n, 0, -1):
		cycles = []
		done = [0] * i
		cur = 0
		for j in range(i):
			if done[j] == 1:
				continue
			else:
				cur = 1
				done[j] = 1
				m = (j + k) % i
				while done[m] == 0:
					cur += 1
					done[m] = 1
					m = (m + k) % i
				cycles.append(cur)
				cur = 0
		cycles.sort(reverse=True)
		cpy = d.copy()
		f = 0
		for j in cycles:
			f = 0
			for m in cpy:
				if cpy[m] >= j:
					cpy[m] -= j
					f = 1
					break
			if f == 0:
				break
		if f == 0:
			continue
		else:
			print(i)
			break


from heapq import *

def root(parent, child):
	while parent[child] != -1:
		child = parent[child]
	return child

def union(parent, size, a, b):
	(root_a, root_b) = (root(parent, a), root(parent, b))
	if root_a == root_b:
		return 0
	elif size[root_a] > size[root_b]:
		parent[root_b] = root_a
		size[root_a] += size[root_b]
		return 1
	else:
		parent[root_a] = root_b
		size[root_b] += size[root_a]
		return 1

def check(cnts, k, length):
	if k % length == 0:
		return True
	parent = [-1 for i in range(length)]
	size = [1 for i in range(length)]
	for i in range(length):
		union(parent, size, i, (i + k) % length)
	heap = [-i for i in cnts if i != 0]
	heapify(heap)
	for i in range(length):
		if parent[i] == -1:
			temp = -heappop(heap)
			if temp < size[i]:
				return False
			else:
				heappush(heap, size[i] - temp)
	return True
t = int(input())
for i in range(t):
	(n, k) = map(int, input().split())
	s = input()
	cnts = [0 for i in range(26)]
	for i in s:
		cnts[ord(i) - 97] += 1
	cnts.sort(reverse=True)
	for length in range(n, 0, -1):
		if check(cnts, k, length):
			print(length)
			break


from bisect import bisect_left as bl
from bisect import bisect_right as br
from heapq import heappush, heappop
import math
from collections import *
from functools import reduce, cmp_to_key
import sys
input = sys.stdin.readline
M = mod = 998244353

def factors(n):
	return sorted(set(reduce(list.__add__, ([i, n // i] for i in range(1, int(n ** 0.5) + 1) if n % i == 0))))

def inv_mod(n):
	return pow(n, mod - 2, mod)

def li():
	return [int(i) for i in input().rstrip('\n').split()]

def st():
	return input().rstrip('\n')

def val():
	return int(input().rstrip('\n'))

def li2():
	return [i for i in input().rstrip('\n')]

def li3():
	return [int(i) for i in input().rstrip('\n')]
cnt = []
k1 = k = 0

def ispos(m):
	global cnt, k, k1
	k = k1
	k = k % m
	if not k:
		return 1
	else:
		req = m // math.gcd(m, k)
		tot = 0
		for i in cnt:
			tot += cnt[i] // req
		return 1 if tot * req >= m else 0
for _ in range(val()):
	(n, k) = li()
	k1 = k
	cnt = Counter(st())
	ans = 0
	for i in range(min(n, 2000)):
		if ispos(i + 1):
			ans = i + 1
	print(ans)


def ans(x):
	print(x)

def gcd(a, b):
	while b:
		(a, b) = (b, a % b)
	return a
t = int(input())
for _ in range(t):
	(n, k) = map(int, input().split())
	s = list(input())
	alphcnt = [0] * 26
	for i in s:
		alphcnt[ord(i) - 97] += 1
	alphcnt.sort(reverse=True)
	end = 1
	for i in range(n, -1, -1):
		g = gcd(i, k)
		if g == 1:
			if alphcnt[0] >= i:
				ans(i)
				end = 0
		else:
			cnt = 0
			p = i // g
			for j in alphcnt:
				cnt += j // p
			if cnt >= g:
				ans(i)
				end = 0
		if end == 0:
			break


import sys
from math import gcd
from bisect import bisect_left as br
from collections import Counter as CO
from collections import defaultdict as dd
input = sys.stdin.readline
t = int(input())
for _ in range(t):
	(n, kk) = map(int, input().split())
	word = list(map(str, input().strip()))
	df = dd(int)
	fact = []
	for k in word:
		df[k] += 1
	ans = 0
	for i in range(1, n + 1):
		maxi = 0
		x = 0
		co = 0
		for j in df:
			if df[j] // i != 0:
				maxi += df[j] // i
		if maxi == 0:
			break
		for j in range(maxi, 0, -1):
			if kk % j == 0:
				maxi = j
				break
		ans = max(ans, maxi * i)
	print(ans)


def binary_search(item, start, end, l):
	if start > end:
		return max(end, 0)
	if start > len(l) - 1:
		return len(l) - 1
	mid = (start + end) // 2
	if l[mid] > item:
		return binary_search(item, start, mid - 1, l)
	elif l[mid] < item:
		return binary_search(item, mid + 1, end, l)
	else:
		return mid

def f():
	(n, k) = map(int, input().split(' '))
	multiplesofk = []
	for i in range(1, k + 1):
		if k % i == 0:
			multiplesofk.append(i)
	string = input()
	counter = [0] * 200
	for i in range(0, len(string)):
		counter[ord(string[i])] += 1
	listofcount = []
	for i in range(ord('a'), ord('z') + 1):
		if counter[i] != 0:
			listofcount.append(counter[i])
	maximum = 0
	for i in range(1, max(listofcount) + 1):
		s = 0
		for j in range(0, len(listofcount)):
			s += listofcount[j] // i
		element = binary_search(s, 0, len(multiplesofk) - 1, multiplesofk)
		maximum = max(maximum, multiplesofk[element] * i)
	print(maximum)
for i in range(int(input())):
	f()


from collections import Counter

def calc_factors(N):
	i = 1
	factors = set()
	while i * i <= N:
		if N % i == 0:
			factors.add(i)
			factors.add(N // i)
		i += 1
	return list(sorted(factors))
T = int(input())
for _ in range(T):
	(N, K) = map(int, input().split())
	L = input()
	C = Counter(L)
	C = list(sorted(Counter(L).values()))
	ans = 0
	factors_k = calc_factors(K)
	for fac in factors_k:
		max_val = 0
		for i in range(1, C[-1] + 1):
			cnt = 0
			idx = 0
			while idx < len(C):
				r = C[idx] // i
				cnt += r
				idx += 1
			if cnt >= fac:
				max_val = max(max_val, i)
		ans = max(ans, fac * max_val)
	print(ans)


from bisect import *
from collections import *
from math import gcd, ceil, sqrt, floor, inf
from heapq import *
from itertools import *
from functools import *
import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

def RL():
	return map(int, sys.stdin.readline().rstrip().split())

def RLL():
	return list(map(int, sys.stdin.readline().rstrip().split()))

def N():
	return int(input())
from types import GeneratorType

def bootstrap(f, stack=[]):

	def wrappedfunc(*args, **kwargs):
		if stack:
			return f(*args, **kwargs)
		else:
			to = f(*args, **kwargs)
			while True:
				if type(to) is GeneratorType:
					stack.append(to)
					to = next(to)
				else:
					stack.pop()
					if not stack:
						break
					to = stack[-1].send(to)
			return to
	return wrappedfunc
mod = 10 ** 9 + 7
farr = [1]
ifa = []

def fact(x, mod=0):
	if mod:
		while x >= len(farr):
			farr.append(farr[-1] * len(farr) % mod)
	else:
		while x >= len(farr):
			farr.append(farr[-1] * len(farr))
	return farr[x]

def ifact(x, mod):
	global ifa
	fact(x, mod)
	ifa.append(pow(farr[-1], mod - 2, mod))
	for i in range(x, 0, -1):
		ifa.append(ifa[-1] * i % mod)
	ifa.reverse()

def per(i, j, mod=0):
	if i < j:
		return 0
	if not mod:
		return fact(i) // fact(i - j)
	return farr[i] * ifa[i - j] % mod

def com(i, j, mod=0):
	if i < j:
		return 0
	if not mod:
		return per(i, j) // fact(j)
	return per(i, j, mod) * ifa[j] % mod

def catalan(n):
	return com(2 * n, n) // (n + 1)

def isprime(n):
	for i in range(2, int(n ** 0.5) + 1):
		if n % i == 0:
			return False
	return True

def floorsum(a, b, c, n):
	if a == 0:
		return b // c * (n + 1)
	if a >= c or b >= c:
		return floorsum(a % c, b % c, c, n) + b // c * (n + 1) + a // c * n * (n + 1) // 2
	m = (a * n + b) // c
	return n * m - floorsum(c, c - b - 1, a, m - 1)

def lowbit(n):
	return n & -n

def inverse(a, m):
	a %= m
	if a <= 1:
		return a
	return (1 - inverse(m, a) * m) // a % m

class BIT:

	def __init__(self, arr):
		self.arr = arr
		self.n = len(arr) - 1

	def update(self, x, v):
		while x <= self.n:
			self.arr[x] += v
			x += x & -x

	def query(self, x):
		ans = 0
		while x:
			ans += self.arr[x]
			x &= x - 1
		return ans

class DSU:

	def __init__(self, n):
		self.c = [-1] * n

	def same(self, x, y):
		return self.find(x) == self.find(y)

	def find(self, x):
		if self.c[x] < 0:
			return x
		self.c[x] = self.find(self.c[x])
		return self.c[x]

	def union(self, u, v):
		(u, v) = (self.find(u), self.find(v))
		if u == v:
			return False
		if self.c[u] > self.c[v]:
			(u, v) = (v, u)
		self.c[u] += self.c[v]
		self.c[v] = u
		return True

	def size(self, x):
		return -self.c[self.find(x)]

class UFS:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.ranks = [0] * n

	def find(self, x):
		if x != self.parent[x]:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, u, v):
		(pu, pv) = (self.find(u), self.find(v))
		if pu == pv:
			return False
		if self.ranks[pu] >= self.ranks[pv]:
			self.parent[pv] = pu
			if self.ranks[pv] == self.ranks[pu]:
				self.ranks[pu] += 1
		else:
			self.parent[pu] = pv

def Prime(n):
	c = 0
	prime = []
	flag = [0] * (n + 1)
	for i in range(2, n + 1):
		if not flag[i]:
			prime.append(i)
			c += 1
		for j in range(c):
			if i * prime[j] > n:
				break
			flag[i * prime[j]] = prime[j]
			if i % prime[j] == 0:
				break
	return (flag, prime)

def dij(s, graph):
	d = {}
	d[s] = 0
	heap = [(0, s)]
	seen = set()
	while heap:
		(dis, u) = heappop(heap)
		if u in seen:
			continue
		seen.add(u)
		for (v, w) in graph[u]:
			if v not in d or d[v] > d[u] + w:
				d[v] = d[u] + w
				heappush(heap, (d[v], v))
	return d

def GP(it):
	return [[ch, len(list(g))] for (ch, g) in groupby(it)]

def lcm(a, b):
	return a * b // gcd(a, b)

def lis(nums):
	res = []
	for k in nums:
		i = bisect.bisect_left(res, k)
		if i == len(res):
			res.append(k)
		else:
			res[i] = k
	return len(res)

class DLN:

	def __init__(self, val):
		self.val = val
		self.pre = None
		self.next = None

def nb(i, j):
	for (ni, nj) in [[i + 1, j], [i - 1, j], [i, j - 1], [i, j + 1]]:
		if 0 <= ni < n and 0 <= nj < m:
			yield (ni, nj)

def topo(n):
	q = deque()
	res = []
	for i in range(1, n + 1):
		if ind[i] == 0:
			q.append(i)
			res.append(i)
	while q:
		u = q.popleft()
		for v in g[u]:
			ind[v] -= 1
			if ind[v] == 0:
				q.append(v)
				res.append(v)
	return res

@bootstrap
def gdfs(r, p):
	if len(g[r]) == 1 and p != -1:
		yield None
	for ch in g[r]:
		if ch != p:
			yield gdfs(ch, r)
	yield None

@bootstrap
def dfs(r):
	vis[r] = 1
	ans[r - 1] = val[r]
	for ch in g[r]:
		if d[ch] > d[r]:
			yield dfs(ch)
			ans[r - 1] = min(ans[r - 1], ans[ch - 1])
	yield None

def f(x, g):
	ans = 0
	for ch in res:
		ans += c[ch] // x
	return ans >= g
t = N()
for i in range(t):
	(n, k) = RL()
	s = input()
	c = Counter(s)
	res = sorted(c.keys(), reverse=True)
	m = k
	for i in range(n, 0, -1):
		k = m % i
		if k == 0:
			ans = i
			break
		g = gcd(k, i)
		a = i // g
		if f(a, g):
			ans = i
			break
	print(ans)


from sys import stdin, stdout
import heapq
import cProfile
from collections import Counter, defaultdict, deque
from functools import reduce
import math

def get_int():
	return int(stdin.readline().strip())

def get_tuple():
	return map(int, stdin.readline().split())

def get_list():
	return list(map(int, stdin.readline().split()))

def solve():
	(n, k) = get_tuple()
	st = input()
	freq_dic = Counter(st)
	max_group_size = max(freq_dic.values())
	ans = 0
	for group_size in range(max_group_size, 0, -1):
		group_length = 0
		for val in freq_dic.values():
			group_length += val // group_size
		while k % group_length != 0 and group_length > 0:
			group_length -= 1
		ans = max(ans, group_length * group_size)
	return ans

def main():
	print(solve())
TestCases = True
if TestCases:
	for i in range(get_int()):
		main()
else:
	main()


import collections
T = int(input())
while T > 0:
	(n, k) = map(int, input().split())
	arr = input()
	dic = collections.defaultdict(int)
	for i in range(n):
		dic[arr[i]] += 1
	parts = []
	for key in dic:
		parts.append(dic[key])
	if n == k:
		print(n)
	elif n > k:
		res = k
		for l in range(k + 1, n + 1):
			start = 1
			cur = (1 + k) % l
			count = 1
			while cur != start:
				count += 1
				cur = (cur + k) % l
			have = 0
			for part in parts:
				have += part // count
			if have * count >= l:
				res = l
		print(res)
	else:
		res = 1
		for l in range(2, n + 1):
			if k % l == 0:
				res = l
			else:
				temp = k % l
				start = 1
				cur = (1 + temp) % l
				count = 1
				while cur != start:
					count += 1
					cur = (cur + temp) % l
				have = 0
				for part in parts:
					have += part // count
				if have * count >= l:
					res = l
		print(res)
	T -= 1


from collections import Counter
import sys
from math import ceil
input = sys.stdin.readline

def prog():
	for _ in range(int(input())):
		(n, k) = map(int, input().split())
		s = input().strip()
		amounts = Counter(s)
		most = list(amounts.values())
		most.sort(reverse=True)
		diff = len(most)
		beauties = []
		for i in range(1, min(int(k ** 0.5 + 1), n + 1)):
			if k % i == 0:
				if i <= n:
					beauties.append(i)
				if k // i <= n:
					beauties.append(k // i)
		lengths = []
		for beauty in beauties:
			l = 1
			r = n // beauty
			while l != r:
				m = ceil((l + r) / 2)
				need = beauty
				idx = 0
				while need > 0 and idx < diff and (most[idx] >= m):
					need -= most[idx] // m
					idx += 1
				if need <= 0:
					l = m
				else:
					r = m - 1
			lengths.append(l * beauty)
		print(max(lengths))
prog()


import math
nb_cases = int(input())
while nb_cases > 0:
	nb_cases -= 1
	(n, k) = [int(x) for x in input().split()]
	s = input()
	nb_letters = [0] * 26
	for pos in range(n):
		nb_letters[ord(s[pos]) - 97] += 1
	min_val = 0
	for x in range(1, n + 1):
		y = x / max(1, math.gcd(k % x, x))
		new_letters = [int(nb_letter / y) for nb_letter in nb_letters]
		nb = sum(new_letters)
		if nb * y >= x:
			min_val = x
	print(min_val)