Given a non-empty array of unique positive integers A, consider the following graph:

There are A.length nodes, labelled A[0] to A[A.length - 1];
There is an edge between A[i] and A[j] if and only if A[i] and A[j] share a common factor greater than 1.

Return the size of the largest connected component in the graph.
 



Example 1:
Input: [4,6,15,35]
Output: 4



Example 2:
Input: [20,50,9,63]
Output: 2



Example 3:
Input: [2,3,6,7,4,12,21,39]
Output: 8


Note:

1 <= A.length <= 20000
1 <= A[i] <= 100000

Source: leetcode | Difficulty: MEDIUM
Tags: Spanning trees

Data structures

Mathematics

Starter code: class Solution:
    def largestComponentSize(self, A: List[int]) -> int:
        

Solutions:
from collections import defaultdict

class Solution:
	MAXPRIME = 100001
	isPrime = [0 for _ in range(MAXPRIME + 1)]
	isPrime[0] = -1
	isPrime[1] = -1
	for i in range(2, MAXPRIME):
		if isPrime[i] == 0:
			for multiple in range(i * i, MAXPRIME + 1, i):
				if isPrime[multiple] == 0:
					isPrime[multiple] = i
			isPrime[i] = i

	def largestComponentSize(self, A: List[int]) -> int:
		label = defaultdict(int)

		def findRoot(key):
			if label[key] > 0:
				label[key] = findRoot(label[key])
				return label[key]
			else:
				return key

		def mergeRoot(k1, k2):
			(r1, r2) = (findRoot(k1), findRoot(k2))
			if r1 != r2:
				(r1, r2) = (min(r1, r2), max(r1, r2))
				label[r1] += label[r2]
				label[r2] = r1
			return r1
		for x in A:
			root_id = 0
			prime_factors = set()
			while Solution.isPrime[x] != -1:
				p = Solution.isPrime[x]
				root_id = findRoot(p) if root_id == 0 else mergeRoot(root_id, p)
				x //= p
			label[root_id] -= 1
		return -min(label.values())


class UF:

	def __init__(self, n):
		self.p = [i for i in range(n)]
		self.s = [1] * n

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

class Solution:
	M = 100000
	sieve = [0] * (M + 1)
	for i in range(2, M + 1):
		if sieve[i] != 0:
			continue
		for j in range(1, M // i + 1):
			sieve[j * i] = i

	def largestComponentSize(self, A: List[int]) -> int:
		g = UF(len(A))
		primes = defaultdict(list)
		for (i, num) in enumerate(A):
			while num > 1:
				q = self.sieve[num]
				primes[q].append(i)
				while num % q == 0:
					num //= q
		for l in primes.values():
			root = g.find(l[0])
			for i in l[1:]:
				node = g.find(i)
				if node != root:
					if g.s[root] < g.s[node]:
						(root, node) = (node, root)
					g.p[node] = root
					g.s[root] += g.s[node]
		return max(g.s)


class DSU:

	def __init__(self, n):
		self.p = list(range(n))
		self.sz = [1] * n

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

	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.sz[x] < self.sz[y]:
			(x, y) = (y, x)
		self.p[y] = x
		self.sz[x] += self.sz[y]

class Solution:

	def largestComponentSize(self, a: List[int]) -> int:
		N = max(a) + 1
		idx = [-1] * N
		for (i, x) in enumerate(a):
			idx[x] = i
		dsu = DSU(N)
		siv = [True] * N
		for i in range(2, N):
			if siv[i]:
				root = idx[i]
				for j in range(2 * i, N, i):
					siv[j] = False
					if idx[j] != -1:
						if root == -1:
							root = idx[j]
						dsu.unite(root, idx[j])
		return max(dsu.sz)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		primes = []
		for x in range(2, int(max(A) ** 0.5) + 1):
			for y in primes:
				if x % y == 0:
					break
			else:
				primes.append(x)
		factors = collections.defaultdict(list)
		for a in A:
			x = a
			for p in primes:
				if p * p > x:
					break
				if x % p == 0:
					factors[a].append(p)
					while x % p == 0:
						x //= p
			if x > 1:
				factors[a].append(x)
				primes.append(x)
		primes = list(set(primes))
		n = len(primes)
		p2i = {p: i for (i, p) in enumerate(primes)}
		parent = [i for i in range(n)]

		def find(i):
			if i != parent[i]:
				parent[i] = find(parent[i])
			return parent[i]

		def union(i, j):
			(pi, pj) = (find(i), find(j))
			if pi != pj:
				parent[pi] = pj
		for a in A:
			if factors[a]:
				p0 = factors[a][0]
				for p in factors[a][1:]:
					union(p2i[p0], p2i[p])
		count = collections.Counter((find(p2i[factors[a][0]]) for a in A if factors[a]))
		return max(count.values())


class ds:

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

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

	def union(self, x, y):
		Ax = self.find(x)
		Ay = self.find(y)
		if Ax == Ay:
			return False
		if self.size[Ax] > self.size[Ay]:
			(Ax, Ay) = (Ay, Ax)
		self.arr[Ax] = Ay
		self.size[Ay] += self.size[Ax]
		return True

def primes(n):
	odds = range(3, n + 1, 2)
	sieve = set(sum([list(range(q * q, n + 1, q + q)) for q in odds], []))
	return [2] + [p for p in odds if p not in sieve]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def factors(n):
			result = set()
			for p in primeNumber:
				while n % p == 0:
					n //= p
					result.add(p)
			if n > 1:
				result.add(n)
			return list(result)
		(n, m) = (len(A), max(A))
		dsa = ds(m + 1)
		primeNumber = primes(round(m ** 0.5) + 1)
		for d in A:
			rest = factors(d)
			for i in rest:
				dsa.union(d, i)
		return Counter([dsa.find(x) for x in A]).most_common(1)[0][1]


import math

class disjoint(object):

	def __init__(self, size):
		self.root_node_size = [1] * size
		self.nodes = [n for n in range(size)]

	def findRoot(self, node):
		while self.nodes[node] != node:
			node = self.nodes[node]
		return node

	def merge(self, val_one, val_two):
		root_one = self.findRoot(val_one)
		root_two = self.findRoot(val_two)
		if root_one == root_two:
			return
		r1size = self.root_node_size[root_one]
		r2size = self.root_node_size[root_two]
		new_root = None
		old_root = None
		if r1size <= r2size:
			new_root = root_two
			old_root = root_one
		else:
			new_root = root_one
			old_root = root_two
		self.root_node_size[new_root] += self.root_node_size[old_root]
		self.root_node_size[old_root] = 0
		self.nodes[old_root] = new_root

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def factors(n):
			known_factors = set()
			while n % 2 == 0:
				known_factors.add(2)
				n //= 2
			for possible_factor in range(3, math.floor(math.sqrt(n)) + 1, 2):
				while n % possible_factor == 0:
					known_factors.add(possible_factor)
					n //= possible_factor
			if n > 2:
				known_factors.add(n)
			return known_factors
		dj = disjoint(len(A))
		known_factors = dict()
		for (i, v) in enumerate(A):
			for p in factors(v):
				if p in known_factors:
					dj.merge(i, known_factors[p])
				known_factors[p] = i
		return max(dj.root_node_size)


class DSU:

	def __init__(self, count):
		self.parent = [i for i in range(count)]
		self.size = [1 for _ in range(count)]
		self.max = 0

	def find(self, x):
		root = x
		while root != self.parent[root]:
			root = self.parent[root]
		while x != root:
			next_root = self.parent[x]
			self.parent[x] = root
			x = next_root
		return root

	def union(self, x, y):
		(r1, r2) = (self.find(x), self.find(y))
		if r1 == r2:
			return
		if self.size[r1] < self.size[r2]:
			self.size[r2] += self.size[r1]
			self.parent[r1] = r2
		else:
			self.size[r1] += self.size[r2]
			self.parent[r2] = r1
		self.max = max(self.max, self.size[r1], self.size[r2])

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = DSU(len(A))

		def getPrimeFactors(n):
			res = set()
			while n % 2 == 0:
				res.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					res.add(i)
					n //= i
			if n > 2:
				res.add(n)
			return res
		prime_to_idx = {}
		for (i, n) in enumerate(A):
			primes = getPrimeFactors(n)
			for prime in primes:
				if prime in prime_to_idx:
					dsu.union(i, prime_to_idx[prime])
				prime_to_idx[prime] = i
		return dsu.max


class UF(object):

	def uf(self, n):
		self.uf = [i for i in range(n)]
		self.size = [1] * n

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

	def union(self, x, y):
		xx = self.find(x)
		yy = self.find(y)
		if xx == yy:
			return
		self.uf[xx] = yy
		self.size[yy] += self.size[xx]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def primefactors(n):
			out = set()
			while n % 2 == 0:
				out.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					out.add(i)
					n //= i
			if n > 2:
				out.add(n)
			return out
		uf = UF()
		uf.uf(len(A))
		prime = {}
		for (i, v) in enumerate(A):
			factors = primefactors(v)
			for p in factors:
				if p in prime:
					uf.union(i, prime[p])
				else:
					prime[p] = i
		return max(uf.size)


class DisjSet:

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

	def find(self, x):
		while self.disj_set[x] >= 0:
			x = self.disj_set[x]
		return x

	def union(self, x, y):
		i = self.find(x)
		j = self.find(y)
		if i == j:
			return
		if self.disj_set[i] < self.disj_set[j]:
			self.disj_set[i] += self.disj_set[j]
			self.disj_set[j] = i
		else:
			self.disj_set[j] += self.disj_set[i]
			self.disj_set[i] = j

	def maxset(self):
		return -min(self.disj_set)

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def gen_primes(n):
			candidates = [1] * n
			for i in range(2, int(math.sqrt(n)) + 1):
				if candidates[i]:
					for j in range(i ** 2, n, i):
						candidates[j] = 0
			return [i for i in range(2, n) if candidates[i]]
		primes = gen_primes(int(math.sqrt(max(A))) + 1)

		def factor(n):
			result = set()
			for i in primes:
				if i > int(math.sqrt(n)):
					break
				if n % i == 0:
					result.add(i)
					while n % i == 0:
						n //= i
			result.add(n)
			return result
		n = len(A)
		disj = DisjSet(n)
		g = {}
		for (i, a) in enumerate(A):
			factors = factor(a)
			for f in factors:
				if f == 1:
					continue
				if f not in g:
					g[f] = i
				else:
					disj.union(i, g[f])
		return disj.maxset()


class UnionFindSet:

	def __init__(self, n):
		self.parents = list(range(n))
		self.ranks = [1] * n

	def find(self, u):
		if u != self.parents[u]:
			self.parents[u] = self.find(self.parents[u])
		return self.parents[u]

	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.parents[pv] = pu
			self.ranks[pu] += self.ranks[pv]
		elif self.ranks[pu] < self.ranks[pv]:
			self.parents[pu] = pv
			self.ranks[pv] += self.ranks[pu]
		else:
			self.parents[pu] = pv
			self.ranks[pv] += self.ranks[pu]
		return True

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def get_prime_factors(n):
			ans = set()
			while n % 2 == 0:
				ans.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					ans.add(i)
					n //= i
			if n > 2:
				ans.add(n)
			return ans
		n = len(A)
		uf = UnionFindSet(n)
		dic = {}
		for (i, a) in enumerate(A):
			primes = get_prime_factors(a)
			for p in primes:
				if p in dic:
					uf.union(i, dic[p])
				dic[p] = i
		return max(uf.ranks)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def decompose(n):

			def rec(n, start):
				for i in range(start, int(math.sqrt(n)) + 1, 2):
					if n % i == 0:
						return rec(n // i, i) | {i}
				return {n}
			if n % 2 == 0:
				while n % 2 == 0:
					n //= 2
				if n == 1:
					return {2}
				return {2} | rec(n, 3)
			return rec(n, 3)
		prime_set = collections.defaultdict(list)
		for i in range(len(A)):
			for f in decompose(A[i]):
				prime_set[f].append(i)
		ls = list(range(len(A)))

		def find(x):
			if ls[x] != x:
				ls[x] = find(ls[x])
			return ls[x]

		def union(x, y):
			ls[find(x)] = find(y)
		for v in prime_set.values():
			for i in range(len(v) - 1):
				union(v[i], v[i + 1])
		return max(Counter([find(i) for i in range(len(A))]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = {}
		rank = {i: 1 for i in range(len(A))}

		def find(x):
			uf.setdefault(x, x)
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px != py:
				if rank[px] > rank[py]:
					(px, py) = (py, px)
				rank[py] += rank[px]
				uf[px] = py

		def primeFactor(x):
			ans = set()
			if not x % 2:
				ans.add(2)
				while not x % 2:
					x //= 2
			for k in range(3, int(sqrt(x)) + 1, 2):
				if not x % k:
					ans.add(k)
					while not x % k:
						x //= k
			if x > 1:
				ans.add(x)
			return ans
		dic = {}
		for i in range(len(A)):
			for k in primeFactor(A[i]):
				dic.setdefault(k, i)
				union(i, dic[k])
		return max(Counter([find(i) for i in range(len(A))]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def sieve():
			i = 2
			while i < len(spf):
				spf[i] = 2
				i += 2
			i = 3
			while i * i < len(spf):
				if spf[i] == i:
					j = i
					while j < len(spf):
						if spf[j] == j:
							spf[j] = i
						j += i
				i += 2
		(spf, di, factors, visited_nums, visited_factors, ans) = ([i for i in range(max(A) + 1)], defaultdict(set), defaultdict(set), set(), set(), 1)
		sieve()
		for num in A:
			x = num
			while x != 1:
				di[spf[x]].add(num)
				factors[num].add(spf[x])
				x //= spf[x]
		for num in A:
			if num in visited_nums:
				continue
			visited_nums.add(num)
			(cur, queue) = (1, deque([]))
			for factor in factors[num]:
				queue.append(factor)
			while queue:
				factor = queue.popleft()
				visited_factors.add(factor)
				for next_num in di[factor]:
					if next_num in visited_nums:
						continue
					visited_nums.add(next_num)
					cur += 1
					for next_factor in factors[next_num]:
						if next_factor in visited_factors:
							continue
						visited_factors.add(next_factor)
						queue.append(next_factor)
			ans = max(ans, cur)
		return ans


class Solution:

	def get_prime_numbers(self, num_to_idx_dict, max_num: int) -> List[int]:
		is_prime_list = [True] * (max_num + 1)
		prime_to_nums_dict = defaultdict(list)
		for i in range(2, max_num // 2 + 1):
			if is_prime_list[i] == False:
				continue
			num = i
			while num <= max_num:
				if num in num_to_idx_dict:
					prime_to_nums_dict[i].append(num_to_idx_dict[num])
				is_prime_list[num] = False
				num += i
		return prime_to_nums_dict

	def find(self, union_list, index: int) -> int:
		if index == union_list[index]:
			return index
		parent = self.find(union_list, union_list[index])
		union_list[index] = parent
		return parent

	def union(self, union_list, index1: int, index2: int) -> None:
		(union1, union2) = (self.find(union_list, index1), self.find(union_list, index2))
		union_list[union1] = union2

	def largestComponentSize(self, A: List[int]) -> int:
		if len(A) == 0:
			return 0
		max_num = max(A)
		union_list = [i for i in range(len(A))]
		count_list = [0] * len(A)
		num_to_idx_dict = dict(list(zip(A, list(range(len(A))))))
		prime_to_nums_dict = self.get_prime_numbers(num_to_idx_dict, max_num)
		for (prime, nums) in list(prime_to_nums_dict.items()):
			for i in range(len(nums) - 1):
				self.union(union_list, nums[i], nums[i + 1])
		for (i, num) in enumerate(A):
			count_list[self.find(union_list, i)] += 1
		return max(count_list)


class DSU:

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

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

	def union(self, x, y):
		xr = self.find(x)
		yr = self.find(y)
		if xr == yr:
			return
		if self.size[xr] >= self.size[yr]:
			self.size[xr] += self.size[yr]
			self.size[yr] = self.size[xr]
			self.parent[yr] = xr
		else:
			self.size[yr] += self.size[xr]
			self.size[xr] = self.size[yr]
			self.parent[xr] = yr

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		N = len(A)
		max_A = max(A)
		is_prime = [True] * (max_A + 1)
		index = {x: i for (i, x) in enumerate(A)}
		dsu = DSU(N)
		for factor in range(2, max_A + 1):
			if is_prime[factor]:
				multiplier = factor << 1
				previous = index.get(factor)
				while multiplier <= max_A:
					is_prime[multiplier] = False
					if multiplier in index:
						if previous is not None:
							dsu.union(previous, index.get(multiplier))
						previous = index[multiplier]
					multiplier += factor
		return max(dsu.size)


class UnionFind(object):

	def uf(self, n):
		self.uf = [i for i in range(n)]
		self.size = [1] * n

	def find(self, x):
		while x != self.uf[x]:
			self.uf[x] = self.uf[self.uf[x]]
			x = self.uf[x]
		return self.uf[x]

	def union(self, x, y):
		x_root = self.find(x)
		y_root = self.find(y)
		if x_root == y_root:
			return
		self.uf[x_root] = y_root
		self.size[y_root] += self.size[x_root]
		self.size[x_root] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def primeFactors(n):
			out = set()
			while n % 2 == 0:
				out.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					out.add(i)
					n //= i
			if n > 2:
				out.add(n)
			return out
		idx_lookup = {A[i]: i for i in range(len(A))}
		uf = UnionFind()
		uf.uf(len(A))
		primeAndItsMultiples = collections.defaultdict(list)
		for i in A:
			factors = primeFactors(i)
			for f in factors:
				primeAndItsMultiples[f].append(i)
		for (idx, multiples) in primeAndItsMultiples.items():
			if multiples:
				root = multiples[0]
				for node in multiples[1:]:
					uf.union(idx_lookup[node], idx_lookup[root])
		return max(uf.size)


from collections import defaultdict as d

class Solution:
	MAXPRIME = 100001
	isPrime = [0 for _ in range(MAXPRIME + 1)]
	isPrime[0] = -1
	isPrime[1] = -1
	for i in range(2, MAXPRIME // 2):
		if isPrime[i] == 0:
			for multiple in range(i * i, MAXPRIME + 1, i):
				if isPrime[multiple] == 0:
					isPrime[multiple] = i

	def largestComponentSize(self, A: List[int]) -> int:
		arr = A
		n = len(arr)
		primeConnections = d(set)
		primeFactorCnts = d(lambda : 0)
		for x in arr:
			if x == 1:
				continue
			primeFactors = set()
			while Solution.isPrime[x] != 0:
				primeFactors.add(Solution.isPrime[x])
				x //= Solution.isPrime[x]
			primeFactors.add(x)
			primeFactors = list(primeFactors)
			if len(primeFactors) > 0:
				primeFactorCnts[primeFactors[0]] += 1
				for i in range(len(primeFactors) - 1):
					for j in range(i + 1, len(primeFactors)):
						primeConnections[primeFactors[i]].add(primeFactors[j])
						primeConnections[primeFactors[j]].add(primeFactors[i])

		def dfs(p, componentSize):
			exploredSet.add(p)
			componentSize[0] += primeFactorCnts[p]
			for nex in primeConnections[p]:
				if nex not in exploredSet:
					dfs(nex, componentSize)
		connectedComponentsSizes = []
		exploredSet = set()
		for p in primeConnections.keys():
			if p not in exploredSet:
				componentSize = [0]
				dfs(p, componentSize)
				connectedComponentsSizes.append(componentSize[0])
		ans = max(connectedComponentsSizes)
		return ans


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		A = set(A)
		n = max(A) + 1
		p = [True] * n
		p[0] = p[1] = False
		(dic1, dic2) = (collections.defaultdict(set), collections.defaultdict(set))
		for i in range(2, n):
			if p[i]:
				for j in range(i, n, i):
					p[j] = False if j != i else True
					if j in A:
						dic1[i].add(j)
						dic2[j].add(i)
		(seen, res) = (set(), 0)
		for num in A:
			if num not in seen:
				seen.add(num)
				(cur, s) = (0, [num])
				while s:
					node = s.pop()
					cur += 1
					for m in dic2[node]:
						for nxt in dic1[m]:
							if nxt not in seen:
								seen.add(nxt)
								s.append(nxt)
						dic1.pop(m)
				res = max(res, cur)
		return res


class DUS(object):

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

	def Find(self, x):
		if self.p[x] == x:
			return x
		tmp = []
		while self.p[x] != x:
			tmp.append(x)
			x = self.p[x]
		for t in tmp:
			self.p[t] = x
		return x

	def Union(self, x, y):
		xr = self.Find(x)
		yr = self.Find(y)
		if xr != yr:
			self.p[yr] = xr
			self.size[xr] += self.size[yr]
			self.size[yr] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def PFD(num):
			ret = set()
			if num % 2 == 0:
				ret.add(2)
				while num % 2 == 0:
					num //= 2
			for i in range(3, int(num ** 0.5) + 1, 2):
				if num % i == 0:
					ret.add(i)
					while num % i == 0:
						num //= i
			if num > 2:
				ret.add(num)
			return ret
		dic = {}
		dus = DUS(len(A))
		for (idx, a) in enumerate(A):
			for p in PFD(a):
				if p in dic:
					dus.Union(dic[p], idx)
				dic[p] = idx
		return max(dus.size)


class UFDS:

	def __init__(self, n, nums):
		self.p = list(range(n + 1))
		self.size = [0] * (n + 1)
		for num in nums:
			self.size[num] = 1

	def find(self, n):
		if n != self.p[n]:
			self.p[n] = self.find(self.p[n])
		return self.p[n]

	def union(self, i, j):
		p1 = self.find(i)
		p2 = self.find(j)
		if p1 != p2:
			if self.size[p1] > self.size[p2]:
				self.p[p2] = p1
				self.size[p1] += self.size[p2]
			else:
				self.p[p1] = p2
				self.size[p2] += self.size[p1]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		hi = max(A)
		ufds = UFDS(hi, A)
		isPrime = [True] * (hi + 1)
		for i in range(2, hi + 1):
			if not isPrime[i]:
				continue
			for j in range(2 * i, hi + 1, i):
				isPrime[j] = False
				if ufds.size[j]:
					ufds.union(i, j)
		return max(ufds.size)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		graphs = {}

		def prime_factors(n):
			factors = set()
			while n % 2 == 0:
				factors.add(2)
				n = n // 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					factors.add(i)
					n = n // i
			if n > 2:
				factors.add(n)
			return factors
		for num in A:
			facts = prime_factors(num)
			if num not in graphs:
				graphs[num] = set()
			for fact in facts:
				if fact not in graphs:
					graphs[fact] = set()
				graphs[fact].add(num)
				graphs[num].add(fact)
		(groups, n_group) = ({}, 0)

		def dfs(factor, group_id):
			groups[factor] = group_id
			for next_factor in graphs[factor]:
				if next_factor not in groups:
					dfs(next_factor, group_id)
		for f in graphs:
			if f not in groups:
				n_group += 1
				dfs(f, n_group)
		group_count = {}
		for num in A:
			group_id = groups[num]
			if group_id not in group_count:
				group_count[group_id] = 0
			group_count[group_id] += 1
		return max(group_count.values())


from typing import Deque, Dict, List, Set, Tuple

def gen_primes():
	yield 2
	prime_divs = collections.defaultdict(list)
	candidate = 3
	while True:
		if candidate in prime_divs:
			for prime_div in prime_divs[candidate]:
				prime_divs[prime_div * 2 + candidate].append(prime_div)
			del prime_divs[candidate]
		else:
			yield candidate
			prime_divs[candidate * candidate] = [candidate]
		candidate += 2

class Solution:

	def __init__(self):
		self.prime_gen = gen_primes()
		self.primes = [next(self.prime_gen) for _ in range(55)]

	def get_primes(self, lower_bound: int) -> List[int]:
		while self.primes[-1] < lower_bound:
			self.primes.append(next(self.prime_gen))
		return self.primes

	def prime_fac_set(self, num: int):
		pfs = set()
		for prime in self.primes:
			if num % prime == 0:
				pfs.add(prime)
			if prime >= num:
				break
		return pfs

	def largestComponentSizeWip(self, A: List[int]) -> int:
		return 0
		pcomps = collections.defaultdict(set)
		edges = collections.defaultdict(set)
		for num in A:
			pfs = self.prime_fac_set(num)
			prv = None
			for prime in pfs:
				pcomps[prime].add(num)
				if prv is None:
					prv = prime
				else:
					edges[prv].add(prime)
					prv = prime
		max_size = 0
		print(edges)
		for (prm, num_set) in list(pcomps.items()):
			the_set = num_set
			the_prm = prm
			while the_prm in edges:
				the_set.update(edges[the_prm])
			max_size = max(max_size, len(the_set))
		return max_size

	def largestComponentSize(self, A: List[int]) -> int:
		lowerb = int(max(A) ** 0.5) + 1
		primes = self.get_primes(lowerb)
		factors = collections.defaultdict(list)
		for a in A:
			x = a
			for p in primes:
				if p * p > x:
					break
				if x % p == 0:
					factors[a].append(p)
					while x % p == 0:
						x //= p
			if x > 1:
				factors[a].append(x)
				primes.append(x)
		primes = list(set(primes))
		n = len(primes)
		p2i = {p: i for (i, p) in enumerate(primes)}
		parent = [i for i in range(n)]

		def find(i):
			if i != parent[i]:
				parent[i] = find(parent[i])
			return parent[i]

		def union(i, j):
			(pi, pj) = (find(i), find(j))
			if pi != pj:
				parent[pi] = pj
		for a in A:
			if factors[a]:
				p0 = factors[a][0]
				for p in factors[a][1:]:
					union(p2i[p0], p2i[p])
		count = collections.Counter((find(p2i[factors[a][0]]) for a in A if factors[a]))
		return max(count.values())


from math import sqrt, floor

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def find(i, parent):
			if parent[i] == i:
				return i
			return find(parent[i], parent)

		def union(i, j, parent, cnt):
			p = find(i, parent)
			q = find(j, parent)
			if p == q:
				return
			if cnt[p] < cnt[q]:
				(p, q) = (q, p)
			cnt[p] += cnt[q]
			parent[q] = p
		m = max(A)
		arr = [True] * (m + 1)
		cnt = [1] * len(A)
		parent = [*list(range(len(A)))]
		for i in range(2, floor(sqrt(m)) + 1):
			if arr[i]:
				k = -1
				for j in range(len(A)):
					if A[j] % i == 0:
						while A[j] % i == 0:
							A[j] = floor(A[j] / i)
						if k == -1:
							k = j
						else:
							union(k, j, parent, cnt)
				for j in range(i * i, m + 1, i):
					arr[j] = False
		A = sorted([(x, i) for (i, x) in enumerate(A) if x > 1])
		for i in range(1, len(A)):
			if A[i - 1][0] == A[i][0]:
				union(A[i - 1][1], A[i][1], parent, cnt)
		return max(cnt)


class Solution:

	def find(self, g, i):
		if i in g:
			gid = g[i]
		else:
			gid = g[i] = i
		if gid != i:
			new_gid = self.find(g, gid)
			g[i] = new_gid
		return g[i]

	def merge(self, g, i, j):
		gid = self.find(g, i)
		gjd = self.find(g, j)
		if gid != gjd:
			g[gid] = gjd

	def prime_factors(self, x):
		if x == 1:
			return [1]
		primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317]
		ans = {x}
		(idx, p) = (0, primes[0])
		while p * p <= x:
			if x % p == 0:
				ans.add(p)
				x //= p
			else:
				idx += 1
				p = primes[idx]
		if x > 1:
			ans.add(x)
		return ans

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		print(n)
		g = dict()
		for x in A:
			pfs = list(self.prime_factors(x))
			for p in pfs[1:]:
				self.merge(g, pfs[0], p)
		groups = [self.find(g, x) for x in A]
		ans = collections.Counter(groups).most_common(1)
		return ans[0][1]


class UnionFind:

	def __init__(self, nodes):
		self.parents = [-1] * len(nodes)
		self.map = {node: idx for (idx, node) in enumerate(nodes)}

	def find(self, node):
		idx = self.map[node]
		orig = idx
		while self.parents[idx] >= 0:
			idx = self.parents[idx]
		(parent, rank) = (idx, abs(self.parents[idx]))
		while self.parents[orig] >= 0:
			temp_parent = self.parents[orig]
			self.parents[orig] = parent
			orig = temp_parent
		return (parent, rank)

	def union(self, n1, n2):
		(idx1, idx2) = (self.map[n1], self.map[n2])
		(parent1, rank1) = self.find(n1)
		(parent2, rank2) = self.find(n2)
		if parent1 == parent2:
			return
		if rank1 >= rank2:
			self.parents[parent1] -= rank2
			self.parents[parent2] = parent1
		else:
			self.parents[parent2] -= rank1
			self.parents[parent1] = parent2

	def get_max_rank(self):
		return abs(min(self.parents))

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		max_num = max(A)
		primes_nodes = collections.defaultdict(set)

		def prime_factors(n):
			original = n
			result = set()
			while n % 2 == 0:
				n = n // 2
				result.add(2)
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					result.add(i)
					n = n // i
			if n > 2:
				result.add(n)
			return result
		uf_obj = UnionFind(A)
		factor_first_multiple_map = {}
		for node in A:
			p_factors = prime_factors(node)
			for pf in p_factors:
				if pf in factor_first_multiple_map:
					uf_obj.union(node, factor_first_multiple_map[pf])
				else:
					factor_first_multiple_map[pf] = node
		return uf_obj.get_max_rank()


from collections import defaultdict

class UnionFind:

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

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

	def union(self, x, y):
		(x_set, y_set) = (self.find(x), self.find(y))
		if x_set == y_set:
			return
		self.parent[x_set] = y_set
		self.size[y_set] += self.size[x_set]
		self.size[x_set] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if len(A) <= 0:
			return 0

		def primeFactors(n):
			out = set()
			while n % 2 == 0:
				out.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					out.add(i)
					n //= i
			if n > 2:
				out.add(n)
			return out
		uf = UnionFind(len(A))
		primeToIndex = {}
		for (i, a) in enumerate(A):
			primes = primeFactors(a)
			for p in primes:
				if p in primeToIndex:
					uf.union(i, primeToIndex[p])
				primeToIndex[p] = i
		return max(uf.size)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		if n < 2:
			return n
		A = set(A)
		if 1 in A:
			A.remove(1)
		if len(A) == 0:
			return 1

		def list_primes(m):
			p = [True] * (m + 1)
			for i in range(2, m + 1):
				if p[i]:
					for j in range(2 * i, m + 1, i):
						p[j] = False
			return [i for i in range(2, m + 1) if p[i]]

		def find_prime_factors(x, prime_list, prime_set):
			if x in prime_set:
				return [x]
			prime_factors = []
			for prime_num in prime_list:
				if prime_num * prime_num > x:
					break
				if x % prime_num == 0:
					prime_factors.append(prime_num)
					while x % prime_num == 0:
						x //= prime_num
			if x != 1:
				prime_factors.append(x)
			return prime_factors

		def prime_decompose(x):
			f = 2
			prime_factors = []
			while x >= f * f:
				if x % f == 0:
					prime_factors.append(f)
					x //= f
				else:
					f += 1
			prime_factors.append(x)
			return prime_factors
		prime_list = list_primes(max(A))
		prime_set = set(prime_list)
		d = {x: find_prime_factors(x, prime_list, prime_set) for x in A}
		all_factors = set()
		for x in A:
			for f in d[x]:
				all_factors.add(f)
		find_dict = {f: f for f in all_factors}
		sink_size = {f: 1 for f in all_factors}

		def find(f):
			if find_dict[f] != f:
				find_dict[f] = find(find_dict[f])
			return find_dict[f]

		def union(fi, fj):
			sink_i = find(fi)
			sink_j = find(fj)
			if sink_i == sink_j:
				return
			if sink_size[sink_i] > sink_size[sink_j]:
				find_dict[sink_j] = sink_i
				sink_size[sink_i] += sink_size[sink_j]
			else:
				find_dict[sink_i] = sink_j
				sink_size[sink_j] += sink_size[sink_i]

		def union_hyperedge(hyperedge):
			for i in range(1, len(hyperedge)):
				union(hyperedge[i], hyperedge[0])

		def union_no_load_balance(hyperedge):
			sink = find(hyperedge[0])
			for f in hyperedge:
				find_dict[find(f)] = sink
				find(f)
		for x in A:
			union_hyperedge(d[x])
		sinks = set()
		for f in all_factors:
			sinks.add(find(f))
		count = {sink: 0 for sink in sinks}
		for x in A:
			count[find(d[x][0])] += 1
		return max(count.values())


(prime, idx) = ([2, 3], [0, 1, 2, 3])

def ensure(n):
	n0 = len(idx)
	if n <= n0:
		return
	prime.extend([x for (i, x) in enumerate(idx[prime[-1] + 1:], prime[-1] + 1) if i == x])
	idx.extend(range(n0, n))
	for x in prime:
		for j in range(max(x, (n0 - 1) // x + 1) * x, n, x):
			idx[j] = x
	for (i, x) in enumerate(idx[n0:], n0):
		if n <= i * i:
			break
		if i != x:
			continue
		prime.append(x)
		for j in range(x * x, n, x):
			idx[j] = x

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		ensure(max(A) + 1)
		(best, src, dst, visited) = (0, {}, {}, set())
		for x in A:
			(x0, ps) = (x, set())
			while x != 1:
				p = idx[x]
				if p not in ps:
					ps.add(p)
					if p in dst:
						dst[p].add(x0)
					else:
						dst[p] = {x0}
				x //= p
			if idx[x0] == x0:
				best = 1
			else:
				src[x0] = ps
		for p in dst:
			if p in visited:
				continue
			(work, grp, xs) = ({p}, set(), set())
			while work:
				grp |= work
				(old, work) = (work, set())
				for p in old:
					xs |= dst[p]
					for x in dst[p] - {p}:
						work |= src[x] - grp
			visited |= grp
			best = max(len(xs), best)
		return best


class DSU:

	def __init__(self):
		self.N = 0
		self.map = {}
		self.parent = []
		self.count = []

	def __contains__(self, obj):
		return obj in self.map

	def add(self, obj):
		if obj in self:
			return
		i = self.N
		self.N += 1
		self.map[obj] = i
		self.parent.append(i)
		self.count.append(0)

	def find(self, obj):
		p = self.parent
		origI = self.map[obj]
		i = origI
		while p[i] != i:
			i = p[i]
		root = i
		i = origI
		while p[i] != i:
			(p[i], i) = (root, p[i])
		return root

	def union(self, objA, objB):
		rObjA = self.find(objA)
		rObjB = self.find(objB)
		if rObjA == rObjB:
			return
		self.count[rObjA] += self.count[rObjB]
		self.parent[rObjB] = rObjA

	def incCount(self, obj):
		rObj = self.find(obj)
		self.count[rObj] += 1
		return self.count[rObj]

class Solution:

	def largestComponentSize(self, nums) -> int:
		UF = DSU()
		max_ = 1
		for num in nums:
			if num == 1:
				continue
			pDs = self.primeDivisors(num)
			pD0 = pDs.pop()
			UF.add(pD0)
			for pD in pDs:
				UF.add(pD)
				UF.union(pD0, pD)
			count = UF.incCount(pD0)
			max_ = max(max_, count)
		return max_

	def primeDivisors(self, num: int):
		x = num
		pDs = set()
		if x % 2 == 0:
			pDs.add(2)
			while x % 2 == 0:
				x >>= 1
		if x % 3 == 0:
			pDs.add(3)
			while x % 3 == 0:
				x //= 3
		div = 5
		d2 = True
		while x >= div * div:
			if x % div == 0:
				pDs.add(div)
				while x % div == 0:
					x //= div
			div += 2 if d2 else 4
			d2 = not d2
		if x > 1:
			pDs.add(x)
		return pDs


class UnionFind(object):

	def __init__(self, n, recursion=False):
		self._par = list(range(n))
		self._size = [1] * n
		self._recursion = recursion

	def root(self, k):
		if self._recursion:
			if k == self._par[k]:
				return k
			self._par[k] = self.root(self._par[k])
			return self._par[k]
		else:
			root = k
			while root != self._par[root]:
				root = self._par[root]
			while k != root:
				(k, self._par[k]) = (self._par[k], root)
			return root

	def unite(self, i, j):
		(i, j) = (self.root(i), self.root(j))
		if i == j:
			return False
		if self._size[i] < self._size[j]:
			(i, j) = (j, i)
		self._par[j] = i
		self._size[i] += self._size[j]
		return True

	def is_connected(self, i, j):
		return self.root(i) == self.root(j)

	def size(self, k):
		return self._size[self.root(k)]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		M = max(A)
		primes = []
		sieve = list(range(M + 1))
		for i in range(2, M + 1):
			if sieve[i] == i:
				primes.append(i)
			for p in primes:
				if i * p > M or sieve[i] < p:
					break
				sieve[i * p] = p
		uf = UnionFind(n)
		color = [-1] * (M + 1)
		for (i, a) in enumerate(A):
			while a != 1:
				p = sieve[a]
				if color[p] != -1:
					uf.unite(i, color[p])
				else:
					color[p] = i
				a //= p
		return max((uf.size(i) for i in range(n)))


class Solution:

	def largestComponentSize(self, nums: List[int]) -> int:
		upper_p = max(nums)
		is_prime = [1] * (upper_p + 1)
		primes = []
		for p in range(2, upper_p + 1):
			if not is_prime[p]:
				continue
			primes.append(p)
			for multi in range(2 * p, upper_p + 1, p):
				is_prime[multi] = 0
		primes_set = set(primes)
		p_par = {p: p for p in primes}
		p_cnt = {p: 0 for p in primes}

		def find_par(ind):
			path = []
			while p_par[ind] != ind:
				path.append(ind)
				ind = p_par[ind]
			for mid in path:
				p_par[mid] = ind
				p_cnt[ind] += p_cnt[mid]
				p_cnt[mid] = 0
			return ind

		def union(p1, p2):
			par1 = find_par(p1)
			par2 = find_par(p2)
			if par1 != par2:
				p_par[par2] = par1
				p_cnt[par1] += p_cnt[par2]
				p_cnt[par2] = 0
			return
		for num in nums:
			if num == 1:
				continue
			factors = []
			for p in primes:
				if p * p > num:
					break
				if num % p == 0:
					factors.append(p)
					while num % p == 0:
						num //= p
			if num in primes_set:
				factors.append(num)
			for other_p in factors[1:]:
				union(factors[0], other_p)
			p_cnt[find_par(factors[0])] += 1
		return max(p_cnt.values())


class Solution:

	def largestComponentSize(self, nums: List[int]) -> int:
		graph = defaultdict(list)
		nodes = set(nums)
		roots = set()
		(m, n) = (len(nums), max(nums))
		primes = [True] * (n + 1)
		for i in range(2, n // 2 + 1):
			if not primes[i]:
				continue
			j = i * 2
			while j <= n:
				primes[j] = False
				if j in nodes:
					graph[i].append(j)
					graph[j].append(i)
					roots.add(i)
				j += i
		ans = self.traverse(graph, roots, nodes)
		return max(ans)

	def traverse(self, graph, roots, real_nodes):
		counts = []
		vztd = set()
		for node in roots:
			if node in vztd:
				continue
			cnt = 0
			vztd.add(node)
			q = [node]
			while q:
				next_q = []
				for n in q:
					if n in real_nodes:
						cnt += 1
					for nab in graph[n]:
						if nab not in vztd:
							vztd.add(nab)
							next_q.append(nab)
				q = next_q
			counts.append(cnt)
		return counts


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def find(v):
			if parent[v] != v:
				parent[v] = find(parent[v])
			return parent[v]

		def union(v1, v2):
			p1 = find(v1)
			p2 = find(v2)
			if p1 not in rank:
				rank[p1] = 0
			if p2 not in rank:
				rank[p2] = 0
			if p1 != p2:
				if rank[p1] > rank[p2]:
					parent[p2] = p1
				else:
					parent[p1] = p2
					if rank[p1] == rank[p2]:
						rank[p2] += 1

		def sieve(n):
			primes = [True] * (n + 1)
			p = 2
			while p * p <= n:
				if primes[p]:
					for i in range(p * 2, n + 1, p):
						primes[i] = False
				p += 1
			return [element for element in range(2, n) if primes[element]]
		rank = {}
		primes = sieve(max(A) // 2 + 1)
		parent = {i: i for i in A + primes}
		for num in A:
			up = int(sqrt(num))
			t = num
			for p in primes:
				if p > up:
					break
				if num % p == 0:
					union(num, p)
				while t % p == 0:
					t //= p
			if t > 1:
				union(num, t)
		return max(Counter([find(n) for n in A]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		N = len(A)
		maxi = max(A)
		p = [i for i in range(N)]
		size = [1] * N
		ret = 1
		(primes, isPrime) = ([], [True] * (maxi + 1))
		for i in range(2, maxi + 1):
			if isPrime[i]:
				primes.append(i)
				for j in range(2, maxi // i + 1):
					isPrime[i * j] = False
		prime2Id = {}

		def find(x):
			if p[x] != x:
				p[x] = find(p[x])
			return p[x]

		def union(x, y):
			nonlocal ret
			(px, py) = (find(x), find(y))
			if px == py:
				return
			p[py] = px
			size[px] += size[py]
			size[py] = 0
			ret = max(ret, size[px])
		for i in range(N):
			a = A[i]
			for f in primes:
				if isPrime[a]:
					if a in prime2Id:
						union(prime2Id[a], i)
					prime2Id[a] = i
					break
				if f * f > A[i]:
					break
				if a % f == 0:
					if f in prime2Id:
						union(prime2Id[f], i)
					prime2Id[f] = i
					while a % f == 0:
						a //= f
				if a == 1:
					break
		return ret


class UF(object):

	def __init__(self, n):
		self.uf = [i for i in range(n)]
		self.size = [1] * n

	def find(self, x):
		while x != self.uf[x]:
			self.uf[x] = self.uf[self.uf[x]]
			x = self.uf[x]
		return x

	def union(self, x, y):
		xr = self.find(x)
		yr = self.find(y)
		if xr == yr:
			return
		self.uf[xr] = yr
		self.size[yr] += self.size[xr]
		self.size[xr] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def pf(n):
			F = set()
			if n % 2 == 0:
				F.add(2)
				while n % 2 == 0:
					n //= 2
			for f in range(3, int(n ** 0.5) + 1, 2):
				if n % f == 0:
					F.add(f)
					while n % f == 0:
						n //= f
			if n > 1:
				F.add(n)
			return F
		uf = UF(len(A))
		pd = {}
		for (i, a) in enumerate(A):
			F = pf(a)
			print((a, F))
			for p in F:
				if p in pd:
					uf.union(i, pd[p])
				pd[p] = i
		return max(uf.size)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def pfactorization(a):
			N = a
			if a >= 2 and a % 2 == 0:
				Gp[2].append(N)
				Gn[N].append(2)
				while a % 2 == 0:
					a //= 2
			for d in range(3, math.floor(a ** (1 / 2)) + 1, 2):
				if d > a:
					break
				if a % d == 0:
					Gn[N].append(d)
					Gp[d].append(N)
					while a % d == 0:
						a //= d
			if a > 1:
				Gp[a].append(N)
				Gn[N].append(a)

		def dfs(curr):
			if curr in seenNodes:
				return 0
			seenNodes.add(curr)
			total = 1
			for p in Gn[curr]:
				if p in seenPrimes:
					continue
				seenPrimes.add(p)
				for owner in Gp[p]:
					total += dfs(owner)
			return total
		Gp = collections.defaultdict(list)
		Gn = collections.defaultdict(list)
		for a in A:
			pfactorization(a)
		(seenPrimes, seenNodes) = (set(), set())
		return max([dfs(a) for a in A])


class UnionFind:

	def __init__(self):
		self.rblong = dict()

	def find(self, n):
		if n not in self.rblong:
			self.rblong[n] = n
			return n
		if n == self.rblong[n]:
			return n
		self.rblong[n] = self.find(self.rblong[n])
		return self.rblong[n]

	def union(self, n1, n2):
		(u1, u2) = (self.find(n1), self.find(n2))
		if u1 == u2:
			return
		self.rblong[u1] = u2
		return

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind()
		prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313]
		for num in A:
			if num == 1:
				continue
			num2 = num
			for i in prime:
				if num2 < i:
					break
				if num2 % i == 0:
					uf.union(num2, i)
					num2 = num2 // i
					if num2 > 1:
						uf.union(num2, i)
					while num2 % i == 0:
						num2 = num2 // i
						if num2 > 1:
							uf.union(num2, i)
			if num2 > 1:
				uf.union(num, num2)
		count = dict()
		for num in A:
			tmp = uf.find(num)
			if tmp not in count:
				count[tmp] = 1
			else:
				count[tmp] += 1
		return max(count.values())


import math
from functools import lru_cache

@lru_cache(None)
def get_primes(n):
	for i in range(2, int(math.sqrt(n)) + 1):
		if n % i == 0:
			return get_primes(n // i) | set([i])
	return set([n])

class DSU:

	def __init__(self, n):
		self.store = list(range(n))

	def find(self, i):
		assert 0 <= i < len(self.store)
		if i != self.store[i]:
			self.store[i] = self.find(self.store[i])
		return self.store[i]

	def union(self, x, y):
		x_idx = self.find(x)
		y_idx = self.find(y)
		self.store[y_idx] = x_idx

class Solution:

	def largestComponentSize(self, a: List[int]) -> int:
		common_primes = defaultdict(list)
		for (i, num) in enumerate(a):
			for prime in get_primes(num):
				common_primes[prime].append(i)
		dsu = DSU(len(a))
		for idxs in list(common_primes.values()):
			for i in range(len(idxs) - 1):
				dsu.union(idxs[i], idxs[i + 1])
		return Counter((dsu.find(i) for i in range(len(a)))).most_common(1)[0][1]


class DisjSet:

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

	def find(self, x):
		while self.disj_set[x] >= 0:
			x = self.disj_set[x]
		return x

	def union(self, x, y):
		i = self.find(x)
		j = self.find(y)
		if i == j:
			return
		if self.disj_set[i] < self.disj_set[j]:
			self.disj_set[i] += self.disj_set[j]
			self.disj_set[j] = i
		else:
			self.disj_set[j] += self.disj_set[i]
			self.disj_set[i] = j

	def maxset(self):
		return -min(self.disj_set)

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def factor(n):
			f = []
			while True:
				for i in range(2, int(math.sqrt(n)) + 1):
					if n % i == 0:
						f.append(i)
						n //= i
						break
				else:
					f.append(n)
					break
			return f
		n = len(A)
		disj = DisjSet(n)
		g = {}
		for (i, a) in enumerate(A):
			for f in factor(a):
				if f not in g:
					g[f] = i
				else:
					disj.union(i, g[f])
		return disj.maxset()


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		(parent, size) = ({x: x for x in A}, {x: 1 for x in A})

		def find(a):
			if parent[a] != a:
				parent[a] = find(parent[a])
			return parent[a]

		def union(a, b):
			if b not in parent:
				parent[b] = b
				size[b] = 0
			(x, y) = (find(a), find(b))
			if x != y:
				if size[x] < size[y]:
					(x, y) = (y, x)
				parent[y] = x
				size[x] += size[y]
		for x in A:
			num = x
			if not x & 1:
				union(x, -2)
				x >>= 1
				while not x & 1:
					x >>= 1
			i = 3
			while i * i <= x:
				if x % i == 0:
					union(num, -i)
					while x % i == 0:
						x //= i
				i += 2
			if x > 1:
				union(num, -x)
		return max(size.values())


from collections import defaultdict

class UnionFind:

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

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

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return
		if self.parents[x] > self.parents[y]:
			(x, y) = (y, x)
		self.parents[x] += self.parents[y]
		self.parents[y] = x

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

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def prime_factorize(n):
			a = set()
			while n % 2 == 0:
				a.add(2)
				n //= 2
			f = 3
			while f * f <= n:
				if n % f == 0:
					a.add(f)
					n //= f
				else:
					f += 2
			if n != 1:
				a.add(n)
			return a
		uf = UnionFind(len(A))
		res = 0
		primes = defaultdict(list)
		for (i, a) in enumerate(A):
			for p in prime_factorize(a):
				primes[p].append(i)
		for (_, indices) in primes.items():
			i0 = indices[0]
			for i1 in indices[1:]:
				uf.union(i0, i1)
		return -min(uf.parents)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind(len(A))
		prime_index = {}
		for (i, n) in enumerate(A):
			pfs = get_prime_factors(n)
			for p in pfs:
				if p in prime_index:
					uf.union(i, prime_index[p])
				prime_index[p] = i
		return max(uf.size)

class UnionFind:

	def __init__(self, N):
		self.uf = [i for i in range(N)]
		self.size = [1] * N

	def find(self, x):
		while x != self.uf[x]:
			x = self.uf[x]
		return x

	def union(self, x, y):
		x_root = self.find(x)
		y_root = self.find(y)
		if x_root == y_root:
			return
		if self.size[x_root] > self.size[y_root]:
			self.uf[y_root] = x_root
			self.size[x_root] += self.size[y_root]
			self.size[y_root] = 0
		else:
			self.uf[x_root] = y_root
			self.size[y_root] += self.size[x_root]
			self.size[x_root] = 0

def get_prime_factors(n):
	prime_factors = set()
	while n % 2 == 0:
		prime_factors.add(2)
		n //= 2
	for d in range(3, int(math.sqrt(n)) + 1, 2):
		while n % d == 0:
			prime_factors.add(d)
			n //= d
	if n > 2:
		prime_factors.add(n)
	return prime_factors


class Solution:

	def primeFactors(self, n):
		pset = set()
		while n % 2 == 0:
			pset.add(2)
			n = n // 2
		for i in range(3, int(math.sqrt(n)) + 1, 2):
			while n % i == 0:
				pset.add(i)
				n = n // i
		if n > 2:
			pset.add(n)
		return pset

	def largestComponentSize(self, A: List[int]) -> int:
		ds = DisjointSet(A)
		primeRoots = {}
		for (i, a) in enumerate(A):
			primes = self.primeFactors(a)
			for p in primes:
				if p in primeRoots:
					ds.union(i, primeRoots[p])
				primeRoots[p] = i
		return max(ds.sizes)

class DisjointSet:

	def __init__(self, elements):
		self.parents = [x for x in range(len(elements))]
		self.sizes = [1] * len(elements)

	def find(self, x):
		while x != self.parents[x]:
			(x, self.parents[x]) = (self.parents[x], self.parents[self.parents[x]])
		return x

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return px
		if self.sizes[px] > self.sizes[py]:
			(py, px) = (px, py)
		self.parents[px] = py
		self.sizes[py] += self.sizes[px]


class UF:

	def __init__(self, n):
		self.f = list(range(n))
		self.cc = [1] * n

	def find(self, x):
		while x != self.f[x]:
			x = self.f[x]
		return x

	def union(self, x, y):
		(fx, fy) = (self.find(x), self.find(y))
		if fx != fy:
			if self.cc[fx] <= self.cc[fy]:
				self.f[fx] = fy
				(self.cc[fx], self.cc[fy]) = (0, self.cc[fx] + self.cc[fy])
			else:
				self.f[fy] = fx
				(self.cc[fy], self.cc[fx]) = (0, self.cc[fx] + self.cc[fy])

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		n = len(A)
		uf = UF(n)

		def getPrimeSets(num, num2primes):
			if num2primes[num]:
				return num2primes[num]
			for i in range(2, int(math.sqrt(num)) + 1):
				if num % i == 0:
					num2primes[num] = getPrimeSets(i, num2primes) | getPrimeSets(num // i, num2primes)
					return num2primes[num]
			num2primes[num] = set([num])
			return num2primes[num]
		num2primes = collections.defaultdict(set)
		for num in sorted(A):
			getPrimeSets(num, num2primes)
		prime2numIdxs = collections.defaultdict(list)
		for (idx, num) in enumerate(A):
			ps = num2primes[num]
			for p in ps:
				prime2numIdxs[p].append(idx)
		for (_, idxs) in list(prime2numIdxs.items()):
			for i in range(len(idxs) - 1):
				uf.union(idxs[i], idxs[i + 1])
		res = 1
		for i in range(n):
			res = max(uf.cc[i], res)
		return res


from collections import defaultdict
from math import sqrt

class DSU(object):

	def __init__(self, n):
		self.ds = list(range(n))

	def find(self, v):
		if self.ds[v] != v:
			self.ds[v] = self.find(self.ds[v])
		return self.ds[v]

	def union(self, p1, p2):
		(pp1, pp2) = (self.find(p1), self.find(p2))
		self.ds[pp1] = pp2

class Solution(object):

	def uniqPrime(self, n):
		l = []
		while n % 2 == 0:
			l.append(2)
			n = n // 2
		for i in range(3, int(sqrt(n)) + 1, 2):
			while n % i == 0:
				l.append(i)
				n = n // i
		if n > 2:
			l.append(n)
		return list(set(l))

	def largestComponentSize(self, A):
		primes = defaultdict(list)
		n = len(A)
		for i in range(n):
			p = self.uniqPrime(A[i])
			for x in p:
				primes[x].append(i)
		uf = DSU(n)
		for i in list(primes.items()):
			vals = i[1]
			for j in range(len(vals) - 1):
				uf.union(vals[j], vals[j + 1])
		return max(Counter([uf.find(i) for i in range(n)]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		cnt = dict([(num, 1) for num in A])
		par = dict([(num, num) for num in A])

		def find(num):
			nonlocal par
			if par[num] != num:
				par[num] = find(par[num])
			return par[num]

		def union(num, num2):
			(root, root2) = (find(num), find(num2))
			if root == root2:
				return
			if root > root2:
				(root, root2) = (root2, root)
			par[root2] = root
			cnt[root] = cnt[root] + cnt[root2]
			cnt[root2] = 0
		primes = [2]
		i = 3
		maxA = max(A)
		while i * i <= 100000:
			is_prime = True
			for prime in primes:
				if i % prime == 0:
					is_prime = False
					break
			if is_prime:
				primes.append(i)
			i += 1
		A = sorted(A)
		prime_set = {}
		for num in A:
			prime_set[num] = set()
			tmp = num
			for prime in primes:
				can_div = False
				while tmp % prime == 0:
					tmp /= prime
					can_div = True
				if can_div:
					prime_set[num].add(prime)
				if prime * prime > num:
					break
			if tmp > 1:
				prime_set[num].add(tmp)
		prime_nums = {}
		for num in prime_set:
			for p in prime_set[num]:
				prime_nums.setdefault(p, [])
				prime_nums[p].append(num)
		for (prime, nums) in prime_nums.items():
			roots = set((find(num) for num in nums))
			if len(roots) <= 1:
				continue
			roots = sorted(list(roots))
			for root in roots[1:]:
				union(roots[0], root)
		return max(cnt.values())


class DSU:

	def __init__(self, n):
		self.sets = list(range(n))
		self.sizes = [1] * n

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x != y:
			if self.sizes[x] < self.sizes[y]:
				(x, y) = (y, x)
			self.sets[y] = x
			self.sizes[x] += self.sizes[y]

	def find(self, x):
		group = self.sets[x]
		while group != self.sets[group]:
			group = self.sets[group]
		self.sets[x] = group
		return group

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		primes = []
		for x in range(2, int(max(A) ** 0.5) + 1):
			for y in primes:
				if x % y == 0:
					break
			else:
				primes.append(x)
		f = {}
		for a in A:
			factors = []
			_a = a
			for prime in primes:
				if prime * prime > a:
					break
				if a % prime == 0:
					factors.append(prime)
				while a % prime == 0:
					a //= prime
			if a > 1:
				factors.append(a)
				primes.append(a)
			f[_a] = factors
		prime_lookup = {p: i for (i, p) in enumerate(primes)}
		dsu = DSU(len(primes))
		for (n, prime_factors) in list(f.items()):
			if prime_factors:
				p0 = prime_factors[0]
			for prime in prime_factors[1:]:
				dsu.union(prime_lookup[p0], prime_lookup[prime])
		counter = collections.Counter((dsu.find(prime_lookup[f[a][0]]) for a in A if f[a]))
		return max(counter.values())


import math

class UnionFind:

	def __init__(self, n):
		self.uf = [i for i in range(n)]
		self.size = [1] * n

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

	def union(self, x, y):
		x_root = self.find(x)
		y_root = self.find(y)
		if x_root == y_root:
			return
		self.uf[x_root] = y_root
		self.size[y_root] += self.size[x_root]
		self.size[x_root] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		d = {}
		uf = UnionFind(len(A))
		for (indx, num) in enumerate(A):
			primes = self.primeFactors(num)
			for prime in primes:
				if prime in d:
					uf.union(indx, d[prime])
				d[prime] = indx
		return max(uf.size)

	def primeFactors(self, n):
		out = set()
		while n % 2 == 0:
			out.add(2)
			n /= 2
		for i in range(3, int(math.sqrt(n)) + 1, 2):
			while n % i == 0:
				out.add(i)
				n /= i
		if n > 2:
			out.add(n)
		return out


from collections import defaultdict

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		small_primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
		label = defaultdict(int)

		def findRoot(key):
			if label[key] > 0:
				label[key] = findRoot(label[key])
				return label[key]
			else:
				return key

		def mergeRoot(k1, k2):
			(r1, r2) = (findRoot(k1), findRoot(k2))
			if r1 != r2:
				(r1, r2) = (min(r1, r2), max(r1, r2))
				label[r1] += label[r2]
				label[r2] = r1
			return r1
		for x in A:
			root_id = 0
			for p in small_primes:
				if p > sqrt(x) + 1:
					break
				elif x % p == 0:
					root_id = findRoot(p) if root_id == 0 else mergeRoot(root_id, p)
					while x % p == 0:
						x //= p
			if x != 1:
				root_id = findRoot(x) if root_id == 0 else mergeRoot(root_id, x)
			label[root_id] -= 1
		return -min(label.values())


class UnionFind:

	def __init__(self, A):
		self._arr = {v: -1 for v in A}

	def union(self, u, v):
		p1 = self.find(u)
		p2 = self.find(v)
		if p1 != p2:
			self._arr[p1] = p2
			return True
		return False

	def find(self, u):
		if self._arr.get(u, -1) == -1:
			return u
		self._arr[u] = self.find(self._arr[u])
		return self._arr[u]

class Solution:

	def factorsOf(self, n):
		factors = set()
		while n % 2 == 0:
			factors.add(2)
			n = n // 2
		for i in range(3, int(sqrt(n)) + 1, 2):
			while n % i == 0:
				factors.add(i)
				n = n // i
		if n > 2:
			factors.add(n)
		return factors

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = UnionFind(A)
		for n in A:
			for factor in self.factorsOf(n):
				dsu.union(n, factor)
		cnt_map = collections.Counter()
		ans = 0
		for v in A:
			p = dsu.find(v)
			cnt_map[p] += 1
			ans = max(cnt_map[p], ans)
		return ans


class UF:

	def __init__(self, n):
		self.p = [i for i in range(n)]
		self.s = [1] * n

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

class Solution:
	sieve = [0] * 100001
	for i in range(2, 100001):
		if sieve[i] != 0:
			continue
		for j in range(1, 100000 // i + 1):
			sieve[j * i] = i

	def largestComponentSize(self, A: List[int]) -> int:

		def add_prime(q, i, primes):
			if q not in primes:
				primes[q] = [i]
			else:
				primes[q].append(i)
		n = len(A)
		g = UF(n)
		primes = {}
		for (i, k) in enumerate(A):
			while k > 1:
				q = self.sieve[k]
				add_prime(q, i, primes)
				while k % q == 0:
					k //= q
		for l in primes.values():
			(j, r) = (l[0], g.find(l[0]))
			for i in l[1:]:
				nd = g.find(i)
				if nd != r:
					g.p[nd] = r
					g.s[r] += g.s[nd]
		return max(g.s)


mxn = 10 ** 5 + 5
pri = [1] * mxn
for i in range(2, mxn):
	if pri[i] == 1:
		pri[i] = i
		j = 2
		while i * j < mxn:
			if pri[i * j] == 1:
				pri[i * j] = i
			j += 1

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dct = [0] * mxn
		res = 0

		def root(i):
			while i != arr[i]:
				i = arr[i]
				arr[i] = arr[arr[i]]
			return i

		def update(i, j):
			r1 = root(i)
			r2 = root(j)
			arr[r1] = r2
			size[r2] += size[r1]
		for num in A:
			dct[pri[num]] += 1
		arr = [i for i in range(mxn)]
		size = [dct[i] for i in range(mxn)]
		for num in A:
			ls = []
			while num != 1:
				ls.append(pri[num])
				num = num // pri[num]
			if len(ls) == 1:
				continue
			for i in range(1, len(ls)):
				if root(ls[0]) != root(ls[i]):
					update(ls[0], ls[i])
		return max(size)


class DS:

	def __init__(self, n):
		self.par = list(range(n))

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

	def union(self, x, y):
		self.par[self.find(x)] = self.find(y)

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		@lru_cache(None)
		def find_prime_factors(num):
			if num == 1:
				return []
			if num <= 3:
				return [num]
			for prime in range(2, int(sqrt(num)) + 1):
				if num % prime == 0:
					break
			else:
				prime = num
			while num % prime == 0:
				num //= prime
			return [prime] + find_prime_factors(num)
		s = {}
		for (i, num) in enumerate(A):
			if num == 1:
				continue
			primes = find_prime_factors(num)
			for prime in primes:
				if prime not in s:
					s[prime] = []
				s[prime] += [i]
		ds = DS(len(A))
		for prime in s:
			for i in range(len(s[prime]) - 1):
				ds.union(s[prime][i], s[prime][i + 1])
		counter = Counter([ds.find(i) for i in range(len(A))])
		return max(counter.values() or [1])


class node:

	def __init__(self, val):
		self.val = val
		self.next = []

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		p = [2]
		for i in range(3, int(max(A) ** 0.5) + 1, 2):
			for y in p:
				if i % y == 0:
					break
			else:
				p.append(i)
		f = collections.defaultdict(list)
		for a in A:
			x = a
			for pp in p:
				if pp ** 2 > x:
					break
				if x % pp == 0:
					f[a].append(pp)
					while x % pp == 0:
						x = x // pp
			if x > 1:
				f[a].append(x)
				p.append(x)
		p = list(set(p))
		n = len(p)
		p2i = {pp: i for (i, pp) in enumerate(p)}
		par = [i for i in range(n)]

		def find(i):
			if i != par[i]:
				par[i] = find(par[i])
			return par[i]

		def union(i, j):
			(pi, pj) = (find(i), find(j))
			if pi != pj:
				par[pi] = pj
		for a in A:
			if f[a]:
				p0 = f[a][0]
				for pp in f[a][1:]:
					union(p2i[p0], p2i[pp])
		c = collections.Counter((find(p2i[f[a][0]]) for a in A if f[a]))
		return max(c.values())


class DSU:

	def __init__(self, N):
		self.p = list(range(N))

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

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		self.p[xr] = yr

class Solution:

	def primes_set(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primes_set(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A):
		n = len(A)
		UF = DSU(n)
		primes = defaultdict(list)
		for (i, num) in enumerate(A):
			pr_set = self.primes_set(num)
			for q in pr_set:
				primes[q].append(i)
		for (_, indexes) in primes.items():
			for i in range(len(indexes) - 1):
				UF.union(indexes[i], indexes[i + 1])
		return max(Counter([UF.find(i) for i in range(n)]).values())


class UFS:

	def __init__(self, N):
		self._parent = list(range(N))

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

	def union(self, x, y):
		(xroot, yroot) = (self.find(x), self.find(y))
		if xroot != yroot:
			self._parent[xroot] = yroot

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def primeFactors(k):
			out = set()
			while k % 2 == 0:
				out.add(2)
				k //= 2
			for i in range(3, int(math.sqrt(k)) + 1, 2):
				while k % i == 0:
					out.add(i)
					k //= i
			if k > 2:
				out.add(k)
			return out
		n = len(A)
		maxa = max(A)
		ufs = UFS(maxa + 1)
		for cur in A:
			factors = primeFactors(cur)
			for f in factors:
				ufs.union(f, cur)
		count = [0] * (maxa + 1)
		for cur in A:
			count[ufs.find(cur)] += 1
		return max(count)


class Primes:

	def __init__(self, N):
		self.N = N
		self.primes = [0] * (N + 1)
		self.get_primes()

	def get_primes(self):
		for i in range(2, self.N + 1):
			if self.primes[i] == 0:
				self.primes[i] = i
				upto = self.N // i
				for j in range(2, upto + 1):
					if self.primes[i * j] == 0:
						self.primes[i * j] = i

	def __call__(self, n):
		if n <= 2:
			return {n}
		p = []
		while n >= 2:
			lp = self.primes[n]
			p.append(lp)
			n = n // lp
		return set(p)

class DisjointSet:

	def __init__(self, primes):
		self.primes = primes
		self.count = 1

	def union(self, setB):
		self.primes |= setB.primes
		self.count += setB.count

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		disjoint_sets = []
		Factors = Primes(max(A))
		rank = [1] * (len(A) + 1)
		parent = [-1] * (len(A) + 1)
		m = dict()
		curr_count = 0

		def get_parent(x):
			if parent[x] == -1:
				return x
			parent[x] = get_parent(parent[x])
			return parent[x]

		def union(x, y):
			parx = get_parent(x)
			pary = get_parent(y)
			if parx == pary:
				return
			if rank[parx] >= rank[pary]:
				rank[parx] += rank[pary]
				parent[pary] = parx
			else:
				rank[pary] += rank[parx]
				parent[parx] = pary
		for (i, val) in enumerate(A):
			val_primes = Factors(val)
			for prime in val_primes:
				if prime in m:
					union(m[prime], i)
				else:
					m[prime] = i
		curr_count = max(rank)
		return curr_count


from typing import List, Set, Tuple

def prime_factors(n: int) -> Set[int]:
	f = set()
	i = 1
	while n % 2 == 0 and n:
		f.add(2)
		n //= 2
	while n % 3 == 0 and n:
		f.add(3)
		n //= 3
	root = int(n ** 0.5) + 1
	while True and n:
		(a, b) = (6 * i + 1, 6 * i - 1)
		while n % a == 0:
			n //= a
			f.add(a)
		while n % b == 0:
			n //= b
			f.add(b)
		if a > root:
			break
		i += 1
	if n > 1:
		f.add(n)
	return f

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		A.sort(reverse=True)
		islands: List[Tuple[Set[int], int]] = []
		primes: Set[int] = set()
		for n in A:
			factors = prime_factors(n)
			first_merged = None
			to_delete: Set[int] = set()
			for (i, (g, v)) in enumerate(islands):
				if factors.isdisjoint(g):
					continue
				if first_merged is None:
					g.update(factors)
					islands[i] = (g, v + 1)
					first_merged = i
				else:
					(gf, vf) = islands[first_merged]
					gf.update(g)
					islands[first_merged] = (gf, vf + v)
					to_delete.add(i)
			primes_inside = factors & primes
			if primes_inside:
				if first_merged is None:
					new_v = len(primes_inside) + 1
					islands.append((factors, new_v))
				else:
					(gf, vf) = islands[first_merged]
					islands[first_merged] = (gf, vf + len(primes_inside))
				primes.difference_update(primes_inside)
			elif first_merged is None:
				if n in factors:
					primes.add(n)
				else:
					islands.append((factors, 1))
			islands = [g for (i, g) in enumerate(islands) if i not in to_delete]
		return max((v for (g, v) in islands))


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		max_p = int(2 + max(A) ** 0.5)
		primes = [2, 3, 5, 7, 11, 13, 17, 19]
		for num in range(20, max_p):
			for p in primes:
				if p * p > num:
					primes.append(num)
					break
				if num % p == 0:
					break
		prime_factors = collections.defaultdict(list)
		members = collections.defaultdict(list)
		for num in A:
			num0 = num
			for prime in primes:
				if prime ** 2 > num:
					if num > 1:
						prime_factors[num0].append(num)
						members[num].append(num0)
					break
				if num % prime == 0:
					prime_factors[num0].append(prime)
					members[prime].append(num0)
				while num % prime == 0:
					num //= prime
		visited_primes = set()
		ans = 0
		for p in members.keys():
			if p in visited_primes:
				continue
			visited_members = set()
			q_prime = collections.deque([p])
			while q_prime:
				pp = q_prime.popleft()
				for m in members[pp]:
					if m in visited_members:
						continue
					visited_members.add(m)
					for ppp in prime_factors[m]:
						if ppp in visited_primes:
							continue
						visited_primes.add(ppp)
						q_prime.append(ppp)
			ans = max(ans, len(visited_members))
		return ans


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def find(n):
			if n not in root:
				return n
			root[n] = find(root[n])
			return root[n]

		def union(n1, n2):
			(root1, root2) = (find(n1), find(n2))
			if root1 == root2:
				return
			(rank1, rank2) = (rank[root1], rank[root2])
			if rank1 > rank2:
				root[root2] = root1
				size[root1] += size[root2]
			elif rank1 < rank2:
				root[root1] = root2
				size[root2] += size[root1]
			else:
				root[root1] = root2
				size[root2] += size[root1]
				rank[root2] += 1

		def find_prime_factors(n):
			factors = set()
			while n % 2 == 0:
				factors.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					factors.add(i)
					n //= i
			if n > 2:
				factors.add(n)
			return factors
		factor_to_num = collections.defaultdict(list)
		for n in A:
			for factor in find_prime_factors(n):
				factor_to_num[factor].append(n)
		root = {}
		rank = {n: 1 for n in A}
		size = {n: 1 for n in A}
		for factor in factor_to_num:
			first_root = find(factor_to_num[factor][0])
			for i in range(1, len(factor_to_num[factor])):
				union(first_root, factor_to_num[factor][i])
		return max(size.values())


class UnionFind(object):

	def uf(self, n):
		self.uf = [i for i in range(n)]
		self.size = [1] * n

	def find(self, x):
		while x != self.uf[x]:
			self.uf[x] = self.uf[self.uf[x]]
			x = self.uf[x]
		return self.uf[x]

	def union(self, x, y):
		x_root = self.find(x)
		y_root = self.find(y)
		if x_root == y_root:
			return
		self.uf[x_root] = y_root
		self.size[y_root] += self.size[x_root]
		self.size[x_root] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def primeFactors(n):
			out = set()
			while n % 2 == 0:
				out.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					out.add(i)
					n //= i
			if n > 2:
				out.add(n)
			return out
		uf = UnionFind()
		uf.uf(len(A))
		primeToIndex = {}
		for (i, a) in enumerate(A):
			primes = primeFactors(a)
			for p in primes:
				if p in primeToIndex:
					uf.union(i, primeToIndex[p])
				primeToIndex[p] = i
		return max(uf.size)


class DSU:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1 for i in range(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, x, y):
		px = self.find(x)
		py = self.find(y)
		if px == py:
			return
		if self.rank[px] > self.rank[py]:
			self.parent[py] = px
			self.rank[px] += self.rank[py]
		else:
			self.parent[px] = py
			self.rank[py] += self.rank[px]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		dsu = DSU(n)
		primes = defaultdict(list)
		for (i, num) in enumerate(A):
			pr_set = self.primes_set(num)
			for q in pr_set:
				primes[q].append(i)
		for (_, indexes) in list(primes.items()):
			for i in range(len(indexes) - 1):
				dsu.union(indexes[i], indexes[i + 1])
		return max(dsu.rank)

	def primes_set(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primes_set(n // i) | set([i])
		return set([n])

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


class UnionFind:

	def __init__(self, num: int):
		self.parents = [i for i in range(num)]
		self.size = [1] * num
		self.max = 1

	def find(self, number: int) -> int:
		if self.parents[number] != number:
			self.parents[number] = self.find(self.parents[number])
		return self.parents[number]

	def merge(self, x: int, other: int):
		parentX = self.find(x)
		parentOther = self.find(other)
		if parentX != parentOther:
			(size_x, size_y) = (self.parents[parentX], self.parents[parentOther])
			self.parents[parentX] = parentOther
			self.size[parentOther] += self.size[parentX]
			if self.size[parentOther] > self.max:
				self.max = self.size[parentOther]

class Solution:

	def primesBefore(self, value: int) -> List[int]:
		candidates = [True] * (value + 1)
		primeList = []
		for i in range(2, value + 1):
			if not candidates[i]:
				continue
			primeList.append(i)
			for j in range(i, value + 1, i):
				candidates[j] = False
		return primeList

	def largestComponentSize(self, A: List[int]) -> int:
		union_find = UnionFind(len(A))
		cache = {}
		primes = self.primesBefore(max(A))
		primeset = set(primes)
		for (index, value) in enumerate(A):
			svalue = value
			primeIndex = 0
			while svalue not in primeset and primes[primeIndex] <= svalue:
				j = primes[primeIndex]
				if svalue % j != 0:
					primeIndex += 1
					continue
				if j not in cache:
					cache[j] = index
				else:
					union_find.merge(index, cache[j])
				if value // j not in cache:
					cache[value // j] = index
				else:
					union_find.merge(index, cache[value // j])
				while svalue % j == 0:
					svalue //= j
				primeIndex += 1
			if svalue == 1:
				continue
			if svalue not in cache:
				cache[svalue] = index
			else:
				union_find.merge(index, cache[svalue])
		return union_find.max


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		n = len(A)
		index = list(range(n))
		size = [1] * n

		def find(i):
			while index[i] != i:
				i = index[i]
			return i

		def setPrimes(i):
			for j in range(2, int(math.sqrt(i)) + 1):
				if i % j == 0:
					return setPrimes(i // j) | set([j])
			return set([i])
		primes = defaultdict(list)
		for i in range(n):
			s = setPrimes(A[i])
			for prime in s:
				primes[prime].append(i)
		for (_, indices) in primes.items():
			for i in range(len(indices) - 1):
				(k, l) = (find(indices[i]), find(indices[i + 1]))
				if k == l:
					continue
				if size[l] > size[k]:
					(k, l) = (l, k)
				index[l] = k
				size[k] += size[l]
		return max(size)


class Solution:

	def largestComponentSize(self, A):
		n = len(A)
		primes = collections.defaultdict(list)
		parents = [i for i in range(n)]

		def find(x):
			if parents[x] != x:
				return find(parents[x])
			return parents[x]

		def union(x, y):
			(xr, yr) = (find(x), find(y))
			if xr > yr:
				parents[xr] = yr
			else:
				parents[yr] = xr

		def primeSet(N):
			for i in range(2, int(math.sqrt(N)) + 1):
				if N % i == 0:
					return {i} | primeSet(N // i)
			return {N}
		for (i, num) in enumerate(A):
			for q in primeSet(num):
				primes[q] += [i]
		for (_, indexes) in primes.items():
			for i in range(len(indexes) - 1):
				union(indexes[i], indexes[i + 1])
		return max(Counter([find(i) for i in range(n)]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def prime_factors(n):
			for i in range(2, int(math.sqrt(n)) + 1):
				if n % i == 0:
					return prime_factors(n // i) | set([i])
			return set([n])
		f = list(range(len(A)))

		def find(x):
			if f[x] != x:
				f[x] = find(f[x])
			return f[x]

		def union(x, y):
			f[find(x)] = find(y)
		p2i = dict()
		for (i, a) in enumerate(A):
			primes = prime_factors(a)
			for p in primes:
				if p in p2i:
					union(i, p2i[p])
				else:
					p2i[p] = find(i)
		counts = Counter(map(find, range(len(A))))
		return counts.most_common(1)[0][1]


import math

class UnionFind:

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

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

	def union(self, x, y):
		(ix, iy) = (self.find(x), self.find(y))
		if ix != iy:
			self.data[ix] = iy
			self.size[iy] += self.size[ix]
			self.size[ix] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def prime_set(num):
			res = set()
			while num % 2 == 0:
				res.add(2)
				num //= 2
			for i in range(3, int(math.sqrt(num)) + 1, 2):
				while num % i == 0:
					res.add(i)
					num //= i
			if num > 2:
				res.add(num)
			return res
		n = len(A)
		uf = UnionFind(n)
		primes_dict = collections.defaultdict(list)
		for (i, num) in enumerate(A):
			pr_set = prime_set(num)
			for p in pr_set:
				primes_dict[p].append(i)
		for indices in primes_dict.values():
			for j in range(1, len(indices)):
				uf.union(indices[j - 1], indices[j])
		return max(collections.Counter((uf.find(i) for i in range(n))).values())

	def gcd_with_bfs(self, A: List[int]) -> int:
		graph = collections.defaultdict(set)
		for i in range(len(A)):
			for j in range(i, len(A)):
				if math.gcd(A[i], A[j]) > 1:
					graph[A[i]].add(A[j])
					graph[A[j]].add(A[i])
		res = 0
		seen = set()
		for a in A:
			if a not in seen:
				node_count = 0
				q = collections.deque([a])
				seen.add(a)
				while q:
					node = q.popleft()
					node_count += 1
					seen.add(node)
					for child in graph[node]:
						if child not in seen:
							seen.add(child)
							q.append(child)
				res = max(res, node_count)
		return res


max_num = 100000
smallest_prime_factors = [None] * (max_num + 1)
smallest_prime_factors[1] = 1
for num in range(2, max_num + 1):
	if smallest_prime_factors[num] is not None:
		continue
	smallest_prime_factors[num] = num
	for multiple in range(num * num, max_num + 1, num):
		if smallest_prime_factors[multiple] is None:
			smallest_prime_factors[multiple] = num

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parents = {}

		def find(x):
			if x not in parents:
				parents[x] = x
			elif parents[x] != x:
				parents[x] = find(parents[x])
			return parents[x]

		def union(x, y):
			(xx, yy) = (find(x), find(y))
			if xx != yy:
				parents[xx] = yy

		def decompose(num):
			if num == 1:
				return [1]
			prime_factor_set = set()
			while num != 1:
				prime_factor_set.add(smallest_prime_factors[num])
				num //= smallest_prime_factors[num]
			return list(prime_factor_set)
		factor = {}
		for num in A:
			prime_factors = decompose(num)
			factor[num] = prime_factors[0]
			for i in range(1, len(prime_factors)):
				union(prime_factors[i - 1], prime_factors[i])
		counts = Counter((find(factor[num]) for num in A))
		return max(counts.values() or [0])


class DSU:

	def __init__(self, N):
		self.parent = list(range(N))

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

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		self.parent[py] = px

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def primeSet(n):
			for i in range(2, int(sqrt(n)) + 1):
				if n % i == 0:
					return primeSet(n // i) | {i}
			return {n}
		table = collections.defaultdict(list)
		for (i, num) in enumerate(A):
			primes = primeSet(num)
			for p in primes:
				table[p].append(i)
		N = len(A)
		dsu = DSU(N)
		for (_, indexes) in list(table.items()):
			for i in range(len(indexes) - 1):
				dsu.union(indexes[i], indexes[i + 1])
		return max(Counter([dsu.find(x) for x in range(N)]).values())


from collections import defaultdict

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def getFactors(n):
			if n == 1:
				return [1]
			factor_set = []
			if n % 2 == 0:
				factor_set.append(2)
				while n % 2 == 0:
					n = n // 2
			if n > 1:
				for i in range(3, math.floor(math.sqrt(n)) + 1, 2):
					if n % i == 0:
						factor_set.append(i)
						while n % i == 0:
							n = n // i
					if n == 1:
						break
			if n > 2:
				factor_set.append(n)
			return factor_set

		def find(parent, n):
			result = parent[n]
			if result != n:
				parent[n] = find(parent, result)
			return parent[n]

		def union(parent, n1, n2):
			r1 = rank[n1]
			r2 = rank[n2]
			x1 = find(parent, n1)
			x2 = find(parent, n2)
			if x1 != x2:
				if r1 >= r2:
					parent[x2] = parent[x1]
					rank[x1] += 1
				else:
					parent[x1] = parent[x2]
					rank[x2] += 1
		max_elem = max(A)
		parent = [i for i in range(max_elem + 1)]
		rank = [0] * (max_elem + 1)
		for item in A:
			factor_set = getFactors(item)
			v1 = find(parent, item)
			if v1 == item:
				union(parent, factor_set[0], v1)
				for factor in factor_set[1:]:
					union(parent, factor_set[0], factor)
		count = defaultdict(int)
		for item in A:
			count[find(parent, item)] += 1
		return max(count.values())


class DSU:

	def __init__(self, N):
		self.p = list(range(N))
		self.sz = [1] * N
		self.max_sz = 1

	def find(self, x):
		while self.p[x] != x:
			self.p[x] = self.p[self.p[x]]
			x = self.p[x]
		return self.p[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return
		if self.sz[xr] < self.sz[yr]:
			(x, y, xr, yr) = (y, x, yr, xr)
		self.p[yr] = xr
		self.sz[xr] += self.sz[yr]
		self.max_sz = max(self.max_sz, self.sz[xr])

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def factorize(n):
			result = set()
			if n % 2 == 0:
				result.add(2)
				while n % 2 == 0:
					n //= 2
			for i in range(3, int(sqrt(n)) + 1, 2):
				if n % i == 0:
					result.add(i)
					while n % i == 0:
						n //= i
			if n > 1:
				result.add(n)
			return result
		if not A:
			return 0
		dsu = DSU(len(A))
		primes = dict()
		for (i, a) in enumerate(A):
			for prime in factorize(a):
				primes.setdefault(prime, []).append(i)
		for indices in primes.values():
			for i in range(len(indices) - 1):
				dsu.union(indices[i], indices[i + 1])
		return dsu.max_sz


def get_prime_factors(num):
	for i in range(2, int(math.sqrt(num)) + 1):
		if num % i == 0:
			return list(set(get_prime_factors(num // i) + [i]))
	return [num]

class DisjointSet:

	def __init__(self):
		self.prime_parents = {}
		self.parent_to_count = {}

	def get_parent(self, prime):
		if prime not in self.prime_parents:
			self.prime_parents[prime] = -1
			return prime
		current = prime
		while self.prime_parents[current] > 0:
			current = self.prime_parents[current]
		return current

	def join(self, left, right):
		left_parent = self.get_parent(left)
		right_parent = self.get_parent(right)
		if left_parent == right_parent:
			return
		if self.prime_parents[left_parent] < self.prime_parents[right_parent]:
			larger = left_parent
			smaller = right_parent
		else:
			larger = right_parent
			smaller = left_parent
		self.prime_parents[larger] += self.prime_parents[smaller]
		self.parent_to_count[larger] = self.parent_to_count.get(larger, 0) + self.parent_to_count.get(smaller, 0)
		self.prime_parents[smaller] = larger

	def add(self, val):
		prime_factors = get_prime_factors(val)
		for (l, r) in zip(prime_factors, prime_factors[1:]):
			self.join(l, r)
		parent = self.get_parent(prime_factors[0])
		self.parent_to_count[parent] = self.parent_to_count.get(parent, 0) + 1

	def get_largest_set_size(self):
		return max(self.parent_to_count.values())

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dj_set = DisjointSet()
		for val in A:
			dj_set.add(val)
		return dj_set.get_largest_set_size()


import math
from collections import deque

class UnionFind:

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

	def find(self, a):
		if self.parent[a] < 0:
			return a
		self.parent[a] = self.find(self.parent[a])
		return self.parent[a]

	def union(self, a, b):
		root_a = self.find(a)
		root_b = self.find(b)
		if root_a != root_b:
			if self.parent[root_a] <= self.parent[root_b]:
				self.parent[root_a] += self.parent[root_b]
				self.parent[root_b] = root_a
			else:
				self.parent[root_b] += self.parent[root_a]
				self.parent[root_a] = root_b
import math
from collections import defaultdict

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def prime_factors(num):
			for i in range(2, int(math.sqrt(num)) + 1):
				if num % i == 0:
					return set([i]) | prime_factors(num // i)
			return set([num])
		uf = UnionFind(len(A))
		d = defaultdict(list)
		for (i, a) in enumerate(A):
			for p in prime_factors(a):
				d[p].append(i)
		for (p, idx_list) in list(d.items()):
			for i in range(len(idx_list) - 1):
				uf.union(idx_list[i], idx_list[i + 1])
		return -min(uf.parent)


class UnionFind:

	def __init__(self, val):
		self.val = val
		self.parent = self

	def union(self, uf):
		uf.find().parent = self.find()

	def find(self):
		if self.parent == self:
			return self
		self.parent = self.parent.find()
		return self.parent

class Solution:

	def primeSet(self, n, cache):
		if n in cache:
			return cache[n]
		for i in range(2, int(sqrt(n)) + 1):
			if n % i == 0:
				cache[n] = self.primeSet(n // i, cache) | set([i])
				return cache[n]
		cache[n] = set([n])
		return cache[n]

	def largestComponentSize(self, A: List[int]) -> int:
		unionFinds = {x: UnionFind(x) for x in A}
		cache = {}
		numbersThatThisPrimeIsAFactor = defaultdict(list)
		for x in A:
			primes = self.primeSet(x, cache)
			for p in primes:
				numbersThatThisPrimeIsAFactor[p].append(x)
		for (_, p) in numbersThatThisPrimeIsAFactor.items():
			for i in range(len(p) - 1):
				unionFinds[p[i]].union(unionFinds[p[i + 1]])
		return max(Counter([unionFinds[x].find().val for x in A]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = [i for i in range(len(A))]
		rank = [0 for i in range(len(A))]

		def prime_factors(n):
			for i in range(2, int(math.sqrt(n)) + 1):
				if n % i == 0:
					return prime_factors(n // i) | set([i])
			return set([n])

		def find(n):
			p = parent[n]
			if p == n:
				return p
			parent[n] = find(parent[n])
			return parent[n]

		def merge(n1, n2):
			r1 = find(n1)
			r2 = find(n2)
			if r1 == r2:
				return
			if rank[r1] < rank[r2]:
				parent[r1] = r2
			elif rank[r1] > rank[r2]:
				parent[r2] = r1
			else:
				parent[r1] = r2
				rank[r2] += 1
		prime_indeces = defaultdict(list)
		for (i, n) in enumerate(A):
			primes = prime_factors(n)
			for p in primes:
				prime_indeces[p].append(i)
		print(prime_indeces)
		for (p, indeces) in list(prime_indeces.items()):
			for i in range(len(indeces) - 1):
				merge(indeces[i], indeces[i + 1])
		count_map = dict()
		best = 0
		for i in parent:
			i = find(i)
			if i in count_map:
				count_map[i] += 1
			else:
				count_map[i] = 1
			best = max(best, count_map[i])
		return best


import numpy as np

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parents = np.arange(len(A))
		counts = np.ones_like(parents)

		def find(i):
			if parents[i] == i:
				return i
			else:
				return find(parents[i])

		def combine(i, j):
			pi = find(i)
			pj = find(j)
			if pi != pj:
				if counts[pi] > counts[pj]:
					parents[pj] = pi
					counts[pi] += counts[pj]
				else:
					parents[pi] = pj
					counts[pj] += counts[pi]
		max_prime = int(np.floor(np.sqrt(max(A)))) + 1
		sieve = [True] * (max_prime + 1)
		for prime in range(2, max_prime + 1):
			if sieve[prime]:
				match = -1
				for i in range(len(A)):
					if A[i] % prime == 0:
						while A[i] % prime == 0:
							A[i] = A[i] // prime
						if match != -1:
							combine(match, i)
						else:
							match = i
				for k in range(prime, max_prime + 1, prime):
					sieve[k] = False
		inds = np.argsort(A)
		for i in range(1, len(A)):
			if A[inds[i]] != 1 and A[inds[i - 1]] == A[inds[i]]:
				combine(inds[i - 1], inds[i])
		return np.max(counts)


class UFS:

	def __init__(self, n):
		self.p = list(range(n))

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

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		self.p[xr] = yr

class Solution:

	def prime_sets(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.prime_sets(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A: List[int]) -> int:
		UF = UFS(len(A))
		primes = collections.defaultdict(list)
		for (i, n) in enumerate(A):
			prime_set = self.prime_sets(n)
			for q in prime_set:
				primes[q].append(i)
		for (_, items) in primes.items():
			for i in range(len(items) - 1):
				UF.union(items[i], items[i + 1])
		return max(Counter([UF.find(i) for i in range(len(A))]).values())


import collections, math

class DSU:

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

	def find(self, p):
		root = p
		while self.parent[root] != root:
			root = self.parent[root]
		while p != root:
			next_node = self.parent[root]
			self.parent[p] = root
			p = next_node
		return root

	def union(self, x, y):
		(r1, r2) = (self.find(x), self.find(y))
		if r1 == r2:
			return
		if self.sizeOf[r1] > self.sizeOf[r2]:
			self.sizeOf[r1] += self.sizeOf[r2]
			self.parent[r2] = r1
		else:
			self.sizeOf[r2] += self.sizeOf[r1]
			self.parent[r1] = r2

class Solution:

	def largestComponentSize(self, A):

		def primeFactorization(n):
			for i in range(2, int(math.sqrt(n)) + 1):
				if n % i == 0:
					return primeFactorization(n // i) | set([i])
			return set([n])
		n = len(A)
		dsu = DSU(n)
		primes = collections.defaultdict(list)
		for i in range(n):
			prime_factors = primeFactorization(A[i])
			for factor in prime_factors:
				primes[factor] += (i,)
		for factor in primes:
			indices = primes[factor]
			size = len(indices)
			for i in range(size - 1):
				dsu.union(indices[i], indices[i + 1])
		components = collections.defaultdict(int)
		for index in range(n):
			components[dsu.find(index)] += 1
		return max(components.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		record = [-1] * n
		primes = collections.defaultdict(list)

		def get_primes(i):
			for j in range(2, int(math.sqrt(i) + 1)):
				if i % j == 0:
					return get_primes(i // j) | set([j])
			return set([i])
			return res

		def find(a):
			if record[a] < 0:
				return a
			record[a] = find(record[a])
			return record[a]

		def union(i, j):
			(a, b) = (find(i), find(j))
			if a != b:
				if a < b:
					record[a] = b
				else:
					record[b] = a
		for (i, v) in enumerate(A):
			primes_set = get_primes(v)
			for j in primes_set:
				primes[j].append(i)
		for (_, indexes) in list(primes.items()):
			for i in range(len(indexes)):
				union(indexes[0], indexes[i])
		res = 0
		mapping = collections.defaultdict(set)
		for i in range(n):
			root = find(i)
			mapping[root].add(i)
			if len(mapping[root]) > res:
				res = len(mapping[root])
		return res


class UnionFind:

	def __init__(self, n):
		self.reps = [i for i in range(n)]
		self.size = [1] * n

	def find(self, x):
		while self.reps[x] != x:
			self.reps[x] = self.reps[self.reps[x]]
			x = self.reps[x]
		return x

	def union(self, x, y):
		x_root = self.find(x)
		y_root = self.find(y)
		if x_root == y_root:
			return
		self.reps[x_root] = y_root
		self.size[y_root] += self.size[x_root]
		self.size[x_root] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def get_prime_factor(n):
			factors = set()
			while n % 2 == 0:
				n //= 2
				factors.add(2)
			while n % 3 == 0:
				n //= 3
				factors.add(3)
			for i in range(5, int(sqrt(n)) + 1):
				while n % i == 0:
					factors.add(i)
					n //= i
			if n > 1:
				factors.add(n)
			return factors
		factor2idx = collections.defaultdict(list)
		for i in range(len(A)):
			for factor in get_prime_factor(A[i]):
				factor2idx[factor].append(i)
		uf = UnionFind(len(A))
		for (factor, indices) in list(factor2idx.items()):
			for idx in indices[1:]:
				uf.union(indices[0], idx)
		return max(uf.size)


class DSU:

	def __init__(self, size):
		self.indexes = {i: i for i in range(size)}
		self.sizes = {i: 1 for i in range(size)}

	def root(self, i):
		node = i
		while i != self.indexes[i]:
			i = self.indexes[i]
		while node != i:
			nnode = self.indexes[node]
			self.indexes[node] = i
			node = nnode
		return i

	def unite(self, i, j):
		(ri, rj) = (self.root(i), self.root(j))
		if ri == rj:
			return
		else:
			self.indexes[rj] = ri
			self.sizes[ri] += self.sizes[rj]

class Solution:

	def primeSet(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primeSet(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A: List[int]) -> int:
		d = collections.defaultdict(list)
		for i in range(len(A)):
			s = self.primeSet(A[i])
			for v in s:
				d[v].append(i)
		dsu = DSU(len(A))
		for k in d:
			for ind in d[k][1:]:
				dsu.unite(d[k][0], ind)
		ans = 1
		for i in range(len(A)):
			ans = max(ans, dsu.sizes[i])
		return ans


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		fa = [i for i in range(len(A))]
		sz = [1] * len(A)

		def find(x):
			if fa[x] != x:
				fa[x] = find(fa[x])
			return fa[x]
		factor = defaultdict(list)
		for i in range(len(A)):
			x = A[i]
			for y in range(2, int(math.sqrt(x)) + 1):
				if not x % y:
					factor[y].append(i)
					while not x % y:
						x //= y
			if x > 1:
				factor[x].append(i)
		for (k, v) in list(factor.items()):
			for j in range(1, len(v)):
				(x, y) = (v[0], v[j])
				(fx, fy) = (find(x), find(y))
				if fx != fy:
					if sz[fx] > sz[fy]:
						sz[fy] += sz[fx]
						fa[fx] = fy
					else:
						sz[fx] += sz[fy]
						fa[fy] = fx
		ans = 0
		for i in range(len(fa)):
			if i == fa[i]:
				ans = max(ans, sz[i])
		return ans


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		dsu = DSU(n)
		prime_dict = defaultdict(list)
		for (i, num) in enumerate(A):
			primes = self.find_p(num)
			for p in primes:
				prime_dict[p].append(i)
		for (_, p_list) in list(prime_dict.items()):
			for j in range(len(p_list)):
				dsu.union(p_list[0], p_list[j])
		return max(Counter((dsu.find(x) for x in range(n))).values())

	def find_p(self, x):
		for i in range(2, int(math.sqrt(x)) + 1):
			if x % i == 0:
				return self.find_p(x // i) | set([i])
		return set([x])

class DSU:

	def __init__(self, n):
		self.sets = list(range(n))

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

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		self.sets[yr] = xr


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def find_prime_factors(num):
			for i in range(2, int(math.sqrt(num)) + 1):
				if num % i == 0:
					return find_prime_factors(num // i) | set([i])
			return set([num])

		def find_root(x):
			if root[x] != x:
				root[x] = find_root(root[x])
			return root[x]

		def union(x, y):
			root[find_root(x)] = root[find_root(y)]
		root = [i for i in range(len(A))]
		prime_factor_to_index = defaultdict(list)
		for (i, num) in enumerate(A):
			prime_factors = find_prime_factors(num)
			for factor in prime_factors:
				prime_factor_to_index[factor].append(i)
		for indices in list(prime_factor_to_index.values()):
			for i in range(1, len(indices)):
				union(indices[i - 1], indices[i])
		root_count = Counter((find_root(i) for i in range(len(A))))
		return max(root_count.values())


class DSU:

	def __init__(self, nums):
		self.nums = [i for i in range(len(nums))]
		self.cnt = [1] * len(nums)

	def find(self, idx):
		if self.nums[idx] == idx:
			return idx
		pidx = self.find(self.nums[idx])
		self.nums[idx] = pidx
		return pidx

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px != py:
			self.nums[px] = self.nums[py]
			self.cnt[py] += self.cnt[px]
		return self.cnt[py]

class Solution:

	def primes_set(self, x):
		for i in range(2, int(x ** 0.5) + 1):
			if x % i == 0:
				return self.primes_set(x // i) | set([i])
		return set([x])

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = DSU(A)
		primes = {}
		for (i, x) in enumerate(A):
			for prime in self.primes_set(x):
				if prime not in primes:
					primes[prime] = []
				primes[prime].append(i)
		ans = 0
		for (_, idxs) in list(primes.items()):
			for i in range(len(idxs) - 1):
				ans = max(ans, dsu.union(idxs[i], idxs[i + 1]))
		return ans


class Solution:

	def largestComponentSize(self, A):

		def getUniqueDivisors(x: int) -> set():
			result = set()
			while x % 2 == 0:
				result.add(2)
				x >>= 1
			i = 3
			while i * i <= x:
				while x % i == 0:
					result.add(i)
					x //= i
				i += 2
			if x > 1:
				result.add(x)
			if x > 1:
				result.add(x)
			return result

		def findParent(parents: List[int], x: int) -> int:
			if parents[x] != x:
				parents[x] = findParent(parents, parents[x])
			return parents[x]
		n = len(A)
		parents = [i for i in range(n)]
		parentByDivisor = {}
		for i in range(n):
			divisors = getUniqueDivisors(A[i])
			for div in divisors:
				if div in parentByDivisor:
					root = findParent(parents, parentByDivisor[div])
					parents[root] = i
				parentByDivisor[div] = i
		counter = [0 for i in range(n)]
		for i in range(n):
			root = findParent(parents, i)
			counter[root] += 1
		return max(counter)


class DisjointSet:

	def __init__(self, num):
		self.forest = list(range(num))

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

	def union(self, x, y):
		self.forest[self.find(x)] = self.find(y)

class Solution:

	def largestComponentSize(self, arr):
		n = len(arr)
		ds = DisjointSet(n)
		primesDict = defaultdict(list)
		for (i, num) in enumerate(arr):
			primes = self.getPrimes(num)
			for p in primes:
				primesDict[p].append(i)
		for li in primesDict.values():
			for i in range(len(li) - 1):
				ds.union(li[i], li[i + 1])
		return max(Counter([ds.find(i) for i in range(n)]).values())

	def getPrimes(self, num):
		for i in range(2, int(math.sqrt(num)) + 1):
			if num % i == 0:
				return self.getPrimes(num // i) | {i}
		return {num}


from math import sqrt
import collections

class Solution:

	def primes(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primes(n // i) | set([i])
		return set([n])

	def find(self, i):
		if self.root[i] == i:
			return i
		self.root[i] = self.find(self.root[i])
		return self.root[i]

	def union(self, i, j):
		ri = self.find(i)
		rj = self.find(j)
		if ri == rj:
			return
		if self.rank[ri] > self.rank[rj]:
			self.root[rj] = ri
		else:
			self.root[ri] = rj
			if self.rank[ri] == self.rank[rj]:
				self.rank[rj] += 1
		return

	def largestComponentSize(self, A: List[int]) -> int:
		self.root = {i: i for i in range(len(A))}
		self.rank = {i: 0 for i in range(len(A))}
		d = collections.defaultdict(set)
		for i in range(len(A)):
			for key in self.primes(A[i]):
				d[key].add(i)
		for key in d:
			temp = list(d[key])
			for x in temp:
				self.union(temp[0], x)
		return max([val for (key, val) in list(collections.Counter([self.find(i) for i in range(len(A))]).items())])


class UnionFind:

	def __init__(self, N):
		self.indices = list(range(N))

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

	def union(self, x, y):
		(x_i, y_i) = (self.find(x), self.find(y))
		self.indices[x_i] = y_i

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		UF = UnionFind(n)
		primes_set = defaultdict(list)

		def get_primes(num):
			for i in range(2, int(math.sqrt(num)) + 1):
				if num % i == 0:
					return get_primes(num // i) | set([i])
			return set([num])
		for (i, num) in enumerate(A):
			for factor in get_primes(num):
				primes_set[factor].append(i)
		for vals in primes_set.values():
			for i in range(len(vals) - 1):
				UF.union(vals[i], vals[i + 1])
		return max(Counter([UF.find(i) for i in range(n)]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		mp = {}
		ans = 0

		def find(a):
			if a not in mp:
				mp[a] = a
			if mp[a] != a:
				mp[a] = find(mp[a])
			return mp[a]

		def union(a, b):
			pa = find(a)
			pb = find(b)
			if pa != pb:
				mp[pa] = pb
		for a in A:
			for factor in self.primes_set(a):
				union(a, factor)
		return collections.Counter([find(a) for a in A]).most_common(1)[0][1]

	def primes_set(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primes_set(n // i) | set([i])
		return set([n])


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		import math
		n = len(A)
		G = collections.defaultdict(set)

		def get_prime_list(target):
			dest = int(math.sqrt(target))
			target_list = list(range(2, target + 1))
			prime_list = []
			while True:
				num_min = min(target_list)
				if num_min >= dest:
					prime_list.extend(target_list)
					break
				prime_list.append(num_min)
				i = 0
				while True:
					if i >= len(target_list):
						break
					elif target_list[i] % num_min == 0:
						target_list.pop(i)
					i += 1
			return prime_list

		def primes_set(n):
			for i in range(2, int(math.sqrt(n)) + 1):
				if n % i == 0:
					return primes_set(n // i) | set([i])
			return set([n])

		def find(x):
			if p[x] != x:
				p[x] = find(p[x])
			return p[x]

		def union(x, y):
			x = find(x)
			y = find(y)
			p[y] = x
		for a in A:
			G[a] = set()
		pdic = collections.defaultdict(set)
		p = list(range(len(A)))
		for (idx, i) in enumerate(A):
			for j in primes_set(i):
				pdic[j].add(idx)
		for (k, v) in list(pdic.items()):
			n = len(v)
			tmp = list(v)
			for i in range(n - 1):
				union(tmp[i], tmp[i + 1])
		tmp = []
		for i in range(len(A)):
			tmp.append(find(i))
		c = Counter(tmp)
		return max(c.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		f = {}

		def find(x):
			f.setdefault(x, x)
			if x != f[x]:
				f[x] = find(f[x])
			return f[x]

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px != py:
				f[px] = py

		def get_primes(n):
			for i in range(2, int(sqrt(n)) + 1):
				if n % i == 0:
					return get_primes(n // i) | {i}
			return {n}
		primes_dict = collections.defaultdict(list)
		for (i, a) in enumerate(A):
			primes = get_primes(a)
			for p in primes:
				primes_dict[p].append(i)
		for (k, indexes) in list(primes_dict.items()):
			for j in range(len(indexes) - 1):
				union(indexes[j], indexes[j + 1])
		return max(collections.Counter((find(i) for i in range(len(A)))).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = {}

		def find(x):
			uf.setdefault(x, x)
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			uf[find(x)] = find(y)

		def primeFactor(x):
			ans = set()
			if not x % 2:
				ans.add(2)
				while not x % 2:
					x //= 2
			for k in range(3, int(sqrt(x)) + 1, 2):
				if not x % k:
					ans.add(k)
				while not x % k:
					x //= k
				if x == 1:
					break
			if x > 1:
				ans.add(x)
			return ans
		for a in A:
			for k in primeFactor(a):
				union(a, k)
		return max(Counter([find(a) for a in A]).values())


class DSU:

	def __init__(self, n):
		self.parent = list(range(n))

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

	def union(self, c, p):
		self.parent[self.find(c)] = self.find(p)

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = DSU(len(A))

		def prime_factorize(n):
			for i in range(2, int(sqrt(n)) + 1):
				if n % i == 0:
					return [i] + prime_factorize(n // i)
			return [n]
		prime2indices = defaultdict(list)
		for (i, n) in enumerate(A):
			for p in prime_factorize(n):
				prime2indices[p].append(i)
		for arr in list(prime2indices.values()):
			for i in range(1, len(arr)):
				dsu.union(arr[0], arr[i])
		aggregate = defaultdict(int)
		for i in range(len(A)):
			aggregate[dsu.find(i)] += 1
		return max(aggregate.values())


import collections as clc
import math
import time

class UnionFind:

	def __init__(self, n: int):
		self.repr = list(range(n))

	def find(self, num: int) -> int:
		if num != self.repr[num]:
			self.repr[num] = self.find(self.repr[num])
		return self.repr[num]

	def union(self, num1: int, num2: int) -> bool:
		r1 = self.find(num1)
		r2 = self.find(num2)
		if r1 == r2:
			return False
		self.repr[r2] = r1
		return True

class Solution:

	def decompose(self, n: int) -> List[int]:
		ans = []
		max_prime = int(math.sqrt(n))
		if n % 2 == 0:
			ans.append(2)
			while n % 2 == 0:
				n //= 2
		prime = 3
		while prime <= max_prime:
			if n % prime == 0:
				ans.append(prime)
				while n % prime == 0:
					n //= prime
			prime += 2
		if n != 1:
			ans.append(n)
		return ans

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		M = max(A)
		node_lists = clc.defaultdict(list)
		for (idx, a) in enumerate(A):
			for prime in self.decompose(a):
				node_lists[prime].append(idx)
		uf = UnionFind(n)
		for nodes in node_lists.values():
			if len(nodes) <= 1:
				continue
			idx1 = nodes[0]
			for idx2 in nodes[1:]:
				uf.union(idx1, idx2)
		return max(clc.Counter([uf.find(idx) for idx in range(n)]).values())


class DSU:

	def __init__(self, n):
		self.p = list(range(n))

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

	def union(self, x, y):
		(x1, y2) = (self.find(x), self.find(y))
		self.p[x1] = y2

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def get_factor_primes(n):
			for i in range(2, int(n ** (1 / 2)) + 1):
				if n % i == 0:
					return set([i]).union(get_factor_primes(n // i))
			return set([n])
		prime = defaultdict(list)
		for (i, n) in enumerate(A):
			primeset = get_factor_primes(n)
			for p in primeset:
				prime[p].append(i)
		N = len(A)
		dsu = DSU(N)
		for (_, indexes) in list(prime.items()):
			for i in range(len(indexes) - 1):
				dsu.union(indexes[i], indexes[i + 1])
		return max(Counter([dsu.find(i) for i in range(N)]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = {}
		size = defaultdict(lambda : 1)

		def ds(a):
			while a in parent:
				a = parent[a]
			return a

		def union(a, b):
			if (a := ds(a)) != (b := ds(b)):
				if size[a] < size[b]:
					(a, b) = (b, a)
				parent[b] = a
				size[a] += size[b]
			return a
		for a in A:
			for d in factors(a):
				union(-d, a)
		return Counter((ds(a) for a in A)).most_common(1)[0][1]
primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317]
FS = {n: {n} for n in primes}
FS[1] = {}

def factors(f):
	if (n := f) not in FS:
		if n & 1:
			FS[f] = factors3(f)
		else:
			n >>= 1
			while n & 1 == 0:
				n >>= 1
			if n == 1:
				FS[f] = {2}
			else:
				FS[f] = {2} | factors3(n)
	return FS.get(f, set())

def factors3(f, start=3):
	if (n := f) not in FS:
		for i in range(start, int(sqrt(n)) + 1, 2):
			if n % i == 0:
				n = n // i
				while n % i == 0:
					n = n // i
				if n == 1:
					FS[f] = {i}
				else:
					FS[f] = {i} | factors3(n, i + 2)
				break
		else:
			FS[f] = {f}
	return FS[f]


class DisjointSet:

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

	def GetParent(self, i):
		if self.parent[i] != i:
			self.parent[i] = self.GetParent(self.parent[i])
		return self.parent[i]

	def Union(self, i, j):
		i_idx = self.GetParent(i)
		j_idx = self.GetParent(j)
		if j_idx == i_idx:
			return
		if self.rank[i_idx] > self.rank[j_idx]:
			self.parent[j_idx] = i_idx
		else:
			if self.rank[i_idx] == self.rank[j_idx]:
				self.rank[j_idx] += 1
			self.parent[i_idx] = j_idx

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def prime_set(n):
			for i in range(2, math.floor(math.sqrt(n)) + 1):
				if n % i == 0:
					return prime_set(n // i) | set([i])
			return set([n])
		ds = DisjointSet(len(A))
		primes = {}
		for i in range(len(A)):
			curr_prime_set = prime_set(A[i])
			for prime in curr_prime_set:
				primes.setdefault(prime, [])
				primes[prime].append(i)
		for key in primes:
			for i in range(len(primes[key]) - 1):
				ds.Union(primes[key][i], primes[key][i + 1])
		set_counter = {}
		for i in range(len(A)):
			set_counter.setdefault(ds.GetParent(i), 0)
			set_counter[ds.GetParent(i)] += 1
		return max(set_counter.values())


class Solution1:

	def largestComponentSize(self, A):
		if not A:
			return 0

		def findAndCompact(l, i):
			if l[i] == i:
				return i
			p = l[i]
			if p >= 0 and l[p] == p:
				return p
			while p >= 0 and l[p] != p:
				p = l[p]
			root = p
			p = i
			while p >= 0 and l[p] != p:
				t = l[p]
				l[p] = root
				p = t
			return root
		slist = [-1] * len(A)
		d = {}
		for i in range(len(A)):
			n = A[i]
			has_factor = False
			for j in range(2, int(sqrt(n)) + 1):
				if n % j == 0:
					has_factor = True
					k = n // j
					ri = -1 if slist[i] < 0 else findAndCompact(slist, slist[i])
					rj = -1 if j not in d else findAndCompact(slist, d[j])
					rk = -1 if k not in d else findAndCompact(slist, d[k])
					if ri < 0 and rj < 0 and (rk < 0):
						slist[i] = d[j] = d[k] = i
					else:
						mm = min([item for item in (ri, rj, rk) if item >= 0])
						if slist[i] >= 0:
							slist[ri] = mm
						if j in d:
							slist[rj] = mm
						if k in d:
							slist[rk] = mm
						slist[i] = d[j] = d[k] = mm
			if not has_factor:
				if A[i] not in d:
					slist[i] = d[A[i]] = i
				else:
					slist[i] = d[A[i]]
		for i in range(len(A)):
			findAndCompact(slist, i)
		cc = Counter(slist)
		m = cc.most_common(2)
		return m[0][1] if m[0][0] != -1 else m[1][1]

class DSU:

	def __init__(self, N):
		self.p = list(range(N))

	def find(self, x):
		n = self.p[x]
		while n >= 0 and self.p[n] != n:
			n = self.p[n]
		root = n
		n = x
		while n >= 0 and self.p[n] != n:
			t = self.p[n]
			self.p[n] = root
			n = t
		return root

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		self.p[xr] = yr

class Solution:

	def primes_set(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primes_set(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A):
		n = len(A)
		UF = DSU(n)
		primes = defaultdict(list)
		for (i, num) in enumerate(A):
			pr_set = self.primes_set(num)
			for q in pr_set:
				primes[q].append(i)
		for (_, indexes) in primes.items():
			for i in range(len(indexes) - 1):
				UF.union(indexes[i], indexes[i + 1])
		return max(Counter([UF.find(i) for i in range(n)]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = {}

		def find(x):
			uf.setdefault(x, x)
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			uf[find(x)] = find(y)
		for (i, a) in enumerate(A):
			if not a % 2:
				union(A[i], 2)
			while not a % 2:
				a //= 2
			for k in range(3, int(sqrt(A[i])) + 1, 2):
				if not a % k:
					union(A[i], k)
				while not a % k:
					a //= k
				if a == 1:
					break
			if a > 1:
				union(A[i], a)
		return max(Counter([find(a) for a in A]).values())


class DUSNode:

	def __init__(self, parent):
		self.parent = parent
		self.size = 0

class DisjointUnionSet:

	def __init__(self):
		self.forest = {}

	def addSet(self, node, key):
		self.forest[key] = node

	def find(self, p):
		while self.forest[p].parent != p:
			self.forest[p].parent = self.forest[self.forest[p].parent].parent
			p = self.forest[p].parent
		return p

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x != y:
			if self.forest[x].size < self.forest[y].size:
				(x, y) = (y, x)
			self.forest[y].parent = x
			self.forest[x].size += self.forest[y].size

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		composites = set()
		primes = []
		prime_factors = {k: v for (k, v) in zip(A, [[] for _ in range(len(A))])}
		maxA = max(A)
		for n in range(2, maxA + 1):
			if n not in composites:
				primes.append(n)
				m = n
				while m <= maxA:
					composites.add(m)
					if m in prime_factors:
						prime_factors[m].append(n)
					m += n
		djus = DisjointUnionSet()
		for p in primes:
			djus.addSet(DUSNode(p), p)
		for pf in list(prime_factors.values()):
			if pf:
				djus.forest[djus.find(pf[0])].size += 1
			for (p1, p2) in zip(pf, pf[1:]):
				djus.union(p1, p2)
		return max([node.size for node in list(djus.forest.values())])


from math import sqrt
from collections import defaultdict, Counter

def get_prime_factors(n):
	for i in range(2, int(sqrt(n) + 1)):
		if n % i == 0:
			return {i} | get_prime_factors(n // i)
	return {n}

class Solution:

	def largestComponentSize(self, A):
		prime_multiples_map = defaultdict(list)
		for v in A:
			for factor in get_prime_factors(v):
				prime_multiples_map[factor].append(v)
		dsu = DSU(A)
		for vertices in list(prime_multiples_map.values()):
			last = vertices[0]
			for v in vertices:
				dsu.union(last, v)
		parents = [dsu.find(v) for v in A]
		counter = Counter(parents)
		return counter.most_common(1)[0][1]

class DSU:

	def __init__(self, nums):
		self.p = {n: n for n in nums}

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px != py:
			self.p[px] = py


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		N = len(A)
		p = [i for i in range(N)]

		def uf(i):
			if i == p[i]:
				return i
			p[i] = uf(p[i])
			return p[i]
		dt = collections.defaultdict(set)

		def prime_factor(index):
			i = A[index]
			while i % 2 == 0:
				dt[2].add(index)
				i //= 2
			for j in range(3, int(A[index] ** 0.5) + 1, 2):
				while i % j == 0:
					dt[j].add(index)
					i //= j
			if i > 2:
				dt[i].add(index)
		cnt = collections.defaultdict(int)
		for i in range(N):
			prime_factor(i)
		for (_, v) in list(dt.items()):
			pi = uf(v.pop())
			while v:
				pj = uf(v.pop())
				p[pj] = pi
		res = 1
		for i in range(N):
			pi = uf(i)
			cnt[pi] += 1
			res = max(res, cnt[pi])
		return res


import sys

class Solution:

	def largestComponentSize(self, a: List[int]) -> int:
		sys.setrecursionlimit(9000000)

		def unify(x: int, y: int):
			f1 = getfa(x)
			f2 = getfa(y)
			if f1 != f2:
				if fa[f1] < fa[f2]:
					fa[f1] += fa[f2]
					fa[f2] = f1
				else:
					fa[f2] += fa[f1]
					fa[f1] = f2

		def getfa(x: int) -> int:
			i = x
			while fa[i] >= 0:
				i = fa[i]
			j = i
			i = x
			while fa[i] >= 0:
				(fa[i], i) = (j, fa[i])
			return j
		n = len(a)
		flag = dict()
		fa = [-1] * n
		ans = 1
		for i in range(0, n):
			v = a[i]
			if v % 2 == 0:
				if 2 not in flag:
					flag[2] = i
				else:
					unify(flag[2], i)
				while v % 2 == 0:
					v >>= 1
			j = 3
			lim = int(sqrt(v)) + 1
			while j <= lim and j <= v:
				if v % j:
					j += 2
					continue
				if j not in flag:
					flag[j] = i
				else:
					unify(flag[j], i)
				while v % j == 0:
					v //= j
				j += 2
			if v > 1:
				if v not in flag:
					flag[v] = i
				else:
					unify(flag[v], i)
		for i in range(0, n):
			if fa[i] < 0:
				ans = max(ans, -fa[i])
		return ans


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		par = [-1] * 100001

		def _find(x):
			if par[x] == -1:
				return x
			par[x] = _find(par[x])
			return par[x]

		def _union(x, y):
			xp = _find(x)
			yp = _find(y)
			if xp != yp:
				par[yp] = xp
		for x in A:
			for i in range(2, int(sqrt(x)) + 1):
				if x % i == 0:
					_union(i, x)
					_union(x, x // i)
		count = 0
		cache = {}
		for x in A:
			xp = _find(x)
			count = max(count, 1 + cache.get(xp, 0))
			cache[xp] = 1 + cache.get(xp, 0)
		return count


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def get_factors(n):
			factors = set()
			while n % 2 == 0:
				factors.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					factors.add(i)
					n //= i
			if n > 2:
				factors.add(n)
			return factors
		roots = [i for i in range(len(A))]

		def find_root(i):
			while i != roots[i]:
				roots[i] = roots[roots[i]]
				i = roots[i]
			return i
		primes = defaultdict(list)
		for i in range(len(A)):
			factors = get_factors(A[i])
			for n in factors:
				primes[n].append(i)
		for values in list(primes.values()):
			for i in range(len(values) - 1):
				roots[find_root(values[i + 1])] = roots[find_root(values[i])]
		ans = 0
		counter = defaultdict(int)
		for i in range(len(roots)):
			counter[find_root(i)] += 1
			ans = max(ans, counter[find_root(i)])
		return ans


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		root = list(range(max(A) + 1))

		def find(i):
			while not root[i] == i:
				root[i] = root[root[i]]
				i = root[i]
			return i

		def union(a, i):
			root[find(a)] = root[find(i)]
		for a in A:
			for i in range(2, int(math.sqrt(a)) + 1):
				if not a % i:
					union(a, i)
					union(a, a // i)
		return Counter([find(a) for a in A]).most_common(1)[0][1]


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def factors(x):
			sq = int(x ** 0.5)
			f = set()
			for i in range(2, sq + 1):
				while x % i == 0:
					x //= i
					f.add(i)
			if x > 1:
				f.add(x)
			return f
		n = len(A)
		parent = [i for i in range(n)]
		sz = [1] * n
		mp = {}

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

		def union(x, y):
			(rx, ry) = (find(x), find(y))
			if rx != ry:
				parent[rx] = ry
				sz[ry] += sz[rx]
		for (i, a) in enumerate(A):
			fs = factors(a)
			for f in fs:
				if f in mp:
					j = mp[f]
					union(j, i)
				mp[f] = i
		return max(sz)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		x = defaultdict(list)

		def _locate(n):
			if not x[n]:
				return n
			x[n] = _locate(x[n])
			return x[n]

		def _isCommon(n, m):
			np = _locate(n)
			mp = _locate(m)
			if np != mp:
				x[mp] = np
		for n in A:
			for i in range(2, int(sqrt(n)) + 1):
				if not n % i:
					_isCommon(i, n)
					_isCommon(n, n // i)
		c = 0
		cache = {}
		for n in A:
			np = _locate(n)
			c = max(c, 1 + cache.get(np, 0))
			cache[np] = 1 + cache.get(np, 0)
		return c


class FU:

	def __init__(self, n):
		self.p = [i for i in range(n)]

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		self.p[py] = px

class Solution:

	def primeFactors(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primeFactors(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A: List[int]) -> int:
		fu = FU(len(A))
		primes = defaultdict(list)
		for i in range(len(A)):
			prime = self.primeFactors(A[i])
			for pr in prime:
				primes[pr].append(i)
		for (k, v) in list(primes.items()):
			for i in range(len(v) - 1):
				fu.union(v[i], v[i + 1])
		c = Counter([fu.find(i) for i in range(len(A))])
		return max(c.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		L = max(A) + 5
		spf = [i for i in range(L)]
		for p in range(2, L):
			if spf[p] != p:
				continue
			for i in range(p * p, L, p):
				spf[i] = min(spf[i], p)

		def primes(n):
			while n > 1:
				yield spf[n]
				n //= spf[n]
		rep = [i for i in range(L)]
		sz = [0] * L

		def find(x):
			if rep[x] != x:
				rep[x] = find(rep[x])
			return rep[x]

		def union(x, y):
			rx = find(x)
			ry = find(y)
			if rx == ry:
				return
			rep[rx] = ry
			sz[ry] += sz[rx]
		for x in A:
			if x < 2:
				continue
			ps = list(primes(x))
			sz[find(ps[0])] += 1
			for i in range(len(ps) - 1):
				union(ps[i], ps[i + 1])
		return max(sz)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = [-1] * 100001

		def find(x):
			if parent[x] == -1:
				return x
			parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			xp = find(x)
			yp = find(y)
			if xp != yp:
				parent[yp] = xp
		for x in A:
			for i in range(2, int(sqrt(x)) + 1):
				if x % i == 0:
					union(i, x)
					union(x, x // i)
		count = 0
		hashmap = {}
		for x in A:
			xp = find(x)
			count = max(count, 1 + hashmap.get(xp, 0))
			hashmap[xp] = 1 + hashmap.get(xp, 0)
		return count


class Solution:

	def find(self, i, parent):
		if parent[i] == -1:
			return i
		parent[i] = self.find(parent[i], parent)
		return parent[i]

	def union(self, i, j, parent):
		rooti = self.find(i, parent)
		rootj = self.find(j, parent)
		if rooti != rootj:
			parent[rooti] = rootj

	def largestComponentSize(self, A: List[int]) -> int:
		hm = defaultdict(int)
		parent = [-1] * 100001
		for i in A:
			for j in range(2, int(sqrt(i)) + 1):
				if i % j == 0:
					self.union(i, j, parent)
					self.union(i // j, i, parent)
		for i in A:
			parenti = self.find(i, parent)
			hm[parenti] += 1
		return max(hm.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		dic = defaultdict(list)

		def primefactor(x):
			s = []
			y = x
			if x % 2 == 0:
				s.append(2)
			while x % 2 == 0:
				x //= 2
			for i in range(3, floor(sqrt(y)) + 1, 2):
				if x % i == 0:
					s.append(i)
				while x % i == 0:
					x //= i
			if x > sqrt(y):
				s.append(x)
			return s
		for i in range(n):
			primes = primefactor(A[i])
			for d in primes:
				dic[d].append(i)
		a = list(range(n))
		sz = [1] * n

		def root(i):
			while i != a[i]:
				a[i] = a[a[i]]
				i = a[i]
			return i

		def find(i, j):
			return root(i) == root(j)

		def union(i, j):
			root_i = root(i)
			root_j = root(j)
			if sz[root_i] > sz[root_j]:
				a[root_j] = root_i
				sz[root_i] += sz[root_j]
				sz[root_j] = 0
			else:
				a[root_i] = root_j
				sz[root_j] += sz[root_i]
				sz[root_i] = 0
		for v in dic.values():
			for i in range(len(v) - 1):
				if find(v[i], v[i + 1]) == False:
					union(v[i], v[i + 1])
		return max(sz)


from math import sqrt
from functools import reduce
from collections import defaultdict

class Disjoint:

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

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px != py:
			(sx, sy) = (self.size[px], self.size[py])
			if sx > sy:
				self.parent[py] = px
				self.size[px] += sy
			else:
				self.parent[px] = py
				self.size[py] += sx

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		fac_to_ind = defaultdict(int)
		un = Disjoint(len(A))
		for (ind, num) in enumerate(A):
			for fac in range(2, int(math.sqrt(num) + 1)):
				if num % fac:
					continue
				for f in [fac, num // fac]:
					if f not in fac_to_ind:
						fac_to_ind[f] = ind
					else:
						un.union(ind, fac_to_ind[f])
			if num not in fac_to_ind:
				fac_to_ind[num] = ind
			else:
				un.union(ind, fac_to_ind[num])
		return max(un.size)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313]
		unions = collections.defaultdict(set)
		for (i, n) in enumerate(A):
			for p in primes:
				if p * p > n:
					break
				while not n % p:
					n //= p
					unions[p].add(i)
			if n > 1:
				unions[n].add(i)
		ids = list(range(len(A)))

		def find(i):
			if ids[i] != i:
				ids[i] = find(ids[i])
			return ids[i]

		def union(l):
			s = set((find(i) for i in l))
			i = s.pop()
			while s:
				j = s.pop()
				ids[j] = i
		for l in list(unions.values()):
			union(l)
		c = collections.Counter((find(i) for i in range(len(A))))
		return max(c.values())


from math import ceil, sqrt
from typing import List

class Solution:
	MAXN = 100001
	spf = [0 for i in range(MAXN)]

	def largestComponentSize(self, A: List[int]) -> int:
		spf = self.spf
		MAXN = self.MAXN

		def sieve():
			spf[1] = 1
			for i in range(2, MAXN):
				spf[i] = i
			for i in range(4, MAXN, 2):
				spf[i] = 2
			for i in range(3, ceil(sqrt(MAXN))):
				if spf[i] == i:
					for j in range(i * i, MAXN, i):
						if spf[j] == j:
							spf[j] = i

		def getFactorization(x):
			ret = []
			while x != 1:
				if not ret or spf[x] != ret[-1]:
					ret.append(spf[x])
				x = x // spf[x]
			return ret
		sieve()
		parents = {0: [0, 0]}

		def find(curr):
			if curr == parents[curr][0]:
				return curr
			return find(parents[curr][0])
		for i in range(len(A)):
			factors = getFactorization(A[i])
			parent = 0
			for f in factors:
				parents.setdefault(f, [f, 0])
				p = find(f)
				if parent != 0 and p != parent:
					parents[parent][1] += parents[p][1]
					parents[p][0] = parent
					parents[p][1] = 0
				else:
					parent = p
			parents[parent][1] += 1
		return max(list(parents.values()), key=lambda x: x[1])[1]


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		amax = max(A)
		plist = [2]
		for k in range(3, int(sqrt(amax)) + 2, 2):
			for p in plist:
				if p * p > k:
					plist.append(k)
					break
				if k % p == 0:
					break
			else:
				plist.append(k)
		pset = set(plist)
		amax //= 2
		n = n1 = n2 = len(A)
		k = 0
		while k < n1:
			x = A[k]
			if x in pset:
				n1 -= 1
				n2 -= 1
				A[k] = A[n1]
				A[n2] = x
				continue
			if x < plist[-1]:
				k += 1
				continue
			prime = True
			for p in plist:
				if p * p > x:
					break
				if x % p == 0:
					prime = False
					break
			if not prime:
				k += 1
			else:
				n1 -= 1
				A[k] = A[n1]
				if x <= amax:
					n2 -= 1
					A[n2] = x
		ans = 1
		left = n - n2 + n1
		while left > ans and n1 > 0:
			n1 -= 1
			x = A[n1]
			found = False
			k = 0
			while k < n1:
				y = A[k]
				p = math.gcd(x, y)
				if p > 1:
					found = True
					n1 -= 1
					A[k] = A[n1]
					while p > 1:
						y //= p
						p = math.gcd(y, p)
					x *= y
				else:
					k += 1
				if k == n1 and found:
					found = False
					k = 0
			k = n - 1
			while k >= n2:
				if x % A[k] == 0:
					A[k] = A[n2]
					n2 += 1
				else:
					k -= 1
			k = n - n2 + n1
			ans = max(ans, left - k)
			left = k
		return ans


import math

class DiscreteSet:

	def __init__(self, N):
		self.parent = [i for i in range(N)]

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

	def union(self, x, y):
		(xp, yp) = (self.findP(x), self.findP(y))
		self.parent[xp] = yp

class Solution:

	def primesSet(self, n):
		for i in range(2, math.floor(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primesSet(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A: List[int]) -> int:
		dset = DiscreteSet(len(A))
		primes = defaultdict(list)
		for (i, num) in enumerate(A):
			prSet = self.primesSet(num)
			print((i, num, prSet))
			for pr in prSet:
				primes[pr].append(i)
		for indices in list(primes.values()):
			for i in range(len(indices) - 1):
				dset.union(indices[i], indices[i + 1])
		cnt = Counter()
		for i in range(len(A)):
			cnt[dset.findP(i)] += 1
		return max(cnt.values())


class UnionFind(object):

	def __init__(self, n):
		self.uf = [i for i in range(n)]
		self.size = [1] * n

	def find(self, x):
		while self.uf[self.uf[x]] != self.uf[x]:
			self.uf[x] = self.uf[self.uf[x]]
		return self.uf[x]

	def union(self, x, y):
		x_root = self.find(x)
		y_root = self.find(y)
		if x_root == y_root:
			return
		self.uf[x_root] = y_root
		self.size[y_root] += self.size[x_root]
		self.size[x_root] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def factors(n):
			ff = set()
			while n % 2 == 0:
				ff.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					ff.add(i)
					n //= i
			if n > 2:
				ff.add(n)
			return ff
		uf = UnionFind(len(A))
		pti = {}
		for (i, el) in enumerate(A):
			primes = factors(el)
			for p in primes:
				if p in pti:
					uf.union(i, pti[p])
				pti[p] = i
		return max(uf.size)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		p = list(range(max(A) + 1))

		def find(x):
			while p[x] != x:
				p[x] = p[p[x]]
				x = p[x]
			return p[x]

		def union(x, y):
			p[find(x)] = p[find(y)]
		for a in A:
			for k in range(2, int(math.sqrt(a) + 1)):
				if a % k == 0:
					union(a, k)
					union(a, a // k)
		return collections.Counter([find(a) for a in A]).most_common(1)[0][1]


from math import sqrt
from collections import Counter

class UnionFind:

	def __init__(self, length):
		self.array = [i for i in range(length)]

	def union(self, x, y):
		xLoc = self.find(x)
		yLoc = self.find(y)
		self.array[xLoc] = yLoc

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

	def most(self):
		for i in range(len(self.array)):
			self.find(i)
		count = Counter(self.array)
		return max(count.values())

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind(len(A))

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

		def primes(x):
			if x == 2:
				return {2}
			if x % 2 == 0:
				return primes(x // 2) | {2}
			for i in range(3, int(sqrt(x)) + 1, 2):
				if x % i == 0:
					return primes(x // i) | {i}
			return {x}
		facts = {}
		for i in range(len(A)):
			for prime in primes(A[i]):
				if prime not in facts:
					facts[prime] = []
				facts[prime].append(i)
		for prime in facts:
			for i in range(len(facts[prime]) - 1):
				uf.union(facts[prime][i], facts[prime][i + 1])
		return uf.most()


class Find:

	def __init__(self, A):
		self.l = list(range(len(A)))

	def find(self, e):
		if self.l[e] != e:
			self.l[e] = self.find(self.l[e])
		return self.l[e]

	def union(self, x, y):
		a = self.find(x)
		b = self.find(y)
		self.l[a] = b

	def primes(self, n):
		for i in range(int(math.sqrt(n)) - 1):
			if n % (i + 2) == 0:
				return self.primes(n // (i + 2)) | set([i + 2])
		return set([n])

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		factors = defaultdict(list)
		find = Find(A)
		for i in range(len(A)):
			c = find.primes(A[i])
			for j in c:
				factors[j].append(i)
		for (x, i) in list(factors.items()):
			for k in range(len(i) - 1):
				find.union(i[k], i[k + 1])
		counts = list(Counter([find.find(i) for i in range(len(A))]).values())
		return max(counts)


import math
import time

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		links = {}
		original_nums = set(A)

		def get_factors(n):
			out = []
			for i in range(2, int(math.sqrt(n)) + 1):
				if n % i == 0:
					out.append(i)
					out.append(n // i)
			return out
		for num in A:
			factors = get_factors(num)
			if num not in links:
				links[num] = [num]
			for x in factors:
				links[num].append(x)
				if x not in links:
					links[x] = [num]
				else:
					links[x].append(num)

		def search(start):
			if start in seen:
				return 1
			stack = [start]
			size = 0
			while stack:
				cur = stack.pop()
				seen.add(cur)
				if cur in original_nums:
					size += 1
				for node in links[cur]:
					if node not in seen:
						stack.append(node)
						seen.add(node)
			return size
		largest = 0
		seen = set()
		for num in A:
			res = search(num)
			largest = max(largest, res)
		return largest


class Solution:

	def largestComponentSize(self, A):
		if not A:
			return 0

		def findAndCompact(l, i):
			if l[i] == i:
				return i
			p = l[i]
			if p >= 0 and l[p] == p:
				return p
			while p >= 0 and l[p] != p:
				p = l[p]
			root = p
			p = i
			while p >= 0 and l[p] != p:
				t = l[p]
				l[p] = root
				p = t
			return root
		slist = [-1] * len(A)
		d = {}
		for i in range(len(A)):
			n = A[i]
			has_factor = False
			for j in range(2, int(sqrt(n)) + 1):
				if n % j == 0:
					has_factor = True
					k = n // j
					ri = -1 if slist[i] < 0 else findAndCompact(slist, slist[i])
					rj = -1 if j not in d else findAndCompact(slist, d[j])
					rk = -1 if k not in d else findAndCompact(slist, d[k])
					if ri < 0 and rj < 0 and (rk < 0):
						slist[i] = d[j] = d[k] = i
					else:
						mm = min([item for item in (ri, rj, rk) if item >= 0])
						if slist[i] >= 0:
							slist[ri] = mm
						if j in d:
							slist[rj] = mm
						if k in d:
							slist[rk] = mm
						slist[i] = d[j] = d[k] = mm
			if not has_factor:
				if A[i] not in d:
					slist[i] = d[A[i]] = i
				else:
					slist[i] = d[A[i]]
		for i in range(len(A)):
			findAndCompact(slist, i)
		cc = Counter(slist)
		m = cc.most_common(1)
		return m[0][1]


class UnionFind:

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

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

	def union(self, i, j):
		pi = self.find(i)
		pj = self.find(j)
		if pi != pj:
			self.parent[max(pi, pj)] = min(pi, pj)
			self.size[min(pi, pj)] += self.size[max(pi, pj)]
			self.size[max(pi, pj)] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def decompose(num):
			if num == 1:
				return []
			res = []
			remain = num
			for factor in range(2, int(math.sqrt(num)) + 1):
				if remain % factor == 0:
					while remain % factor == 0:
						remain //= factor
					res.append(factor)
			if remain > 1 and num % remain == 0:
				res.append(remain)
			return res
		unions = UnionFind(len(A))
		factor_index = collections.defaultdict(int)
		for (idx, num) in enumerate(A):
			factors = decompose(num)
			unions.size[idx] += 1
			for factor in factors:
				if factor not in factor_index:
					factor_index[factor] = idx
				unions.union(factor_index[factor], idx)
		return max(unions.size)


class UnionFind:

	def __init__(self, n):
		self.uf = list(range(n))
		self.size = defaultdict(lambda : 1)

	def find(self, i):
		if self.uf[i] != i:
			self.uf[i] = self.find(self.uf[i])
		return self.uf[i]

	def union(self, a, b):
		(x, y) = (self.find(a), self.find(b))
		if x == y:
			return
		self.uf[x] = self.uf[y]
		self.size[y] += self.size[x]
		del self.size[x]

def factors(n):
	if n % 2 == 0:
		yield 2
	while n % 2 == 0:
		n //= 2
	for i in range(3, int(n ** 0.5) + 2, 2):
		if i > n:
			break
		if n % i == 0:
			yield i
		while n % i == 0:
			n //= i
	if n > 2:
		yield n

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		u = UnionFind(len(A))
		x = {}
		for (i, a) in enumerate(A):
			for f in factors(a):
				if f in x:
					u.union(i, x[f])
				x[f] = i
		return max(u.size.values())


class Solution:

	def __init__(self):
		self.prime = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317]

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		factors_2_nodes = dict()
		B = [[] for i in range(0, n)]
		for i in range(0, n):
			num = A[i]
			found_factor = True
			while num > 1 and found_factor:
				found_factor = False
				limit = int(sqrt(num + 1))
				for f in self.prime:
					if f > limit:
						break
					if num % f == 0:
						if f not in B[i]:
							B[i].append(f)
							if f in factors_2_nodes:
								factors_2_nodes[f].append(i)
							else:
								factors_2_nodes[f] = [i]
						num //= f
						found_factor = True
						break
				if not found_factor and num not in B[i]:
					B[i].append(num)
					if num in factors_2_nodes:
						factors_2_nodes[num].append(i)
					else:
						factors_2_nodes[num] = [i]
		v = [False] * n
		m = 0
		for i in range(0, n):
			if v[i]:
				continue
			queue = [i]
			c = 0
			while queue:
				q = queue.pop()
				if v[q]:
					continue
				v[q] = True
				c += 1
				for f in B[q]:
					for node in factors_2_nodes[f]:
						if not v[node]:
							queue.append(node)
					factors_2_nodes[f] = []
			if c > m:
				m = c
		return m


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		self.ret = 0
		record = {}
		disjoint = [-1] * len(A)

		def find(x):
			idx = x
			while disjoint[idx] >= 0:
				idx = disjoint[idx]
			while disjoint[x] >= 0:
				tmp = disjoint[x]
				disjoint[x] = idx
				x = tmp
			return idx

		def union(a, b):
			if a == b:
				return
			a_idx = find(a)
			b_idx = find(b)
			if a_idx == b_idx:
				return
			disjoint[a_idx] += disjoint[b_idx]
			disjoint[b_idx] = a_idx
			self.ret = min(self.ret, disjoint[a_idx])

		def factor(x, idx):
			if x < 3:
				union(record.get(x, idx), idx)
				record[x] = idx
				return
			if x % 2 == 0:
				union(record.get(2, idx), idx)
				record[2] = idx
				while x % 2 == 0:
					x = x // 2
			i = 3
			while i * i <= x:
				if x % i == 0:
					union(record.get(i, idx), idx)
					record[i] = idx
				while x % i == 0:
					x = x // i
				i += 2
			if x > 1:
				union(record.get(x, idx), idx)
				record[x] = idx
		factors = [factor(A[i], i) for i in range(len(A))]
		return -self.ret


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = max(A)
		ans = 0
		uf = UF(n)
		count = collections.Counter()
		for a in A:
			for num in range(2, int(sqrt(a) + 1)):
				if a % num == 0:
					uf.union(a, num)
					uf.union(a, a // num)
		for a in A:
			pa = uf.find(a)
			count[pa] += 1
			ans = max(ans, count[pa])
		return ans

class UF:

	def __init__(self, n: int):
		self.rank = [0] * (n + 1)
		self.parent = [i for i in range(n + 1)]

	def union(self, u: int, v: int) -> None:
		pu = self.parent[u]
		pv = self.parent[v]
		if pu == pv:
			return
		if self.rank[pu] < self.rank[pv]:
			self.parent[pu] = pv
		elif self.rank[pv] < self.rank[pu]:
			self.parent[pv] = pu
		else:
			self.parent[pu] = pv
			self.rank[pv] += 1

	def find(self, u: int) -> int:
		while u != self.parent[u]:
			self.parent[u] = self.parent[self.parent[u]]
			u = self.parent[u]
		return u


class UnionFind(object):

	def __init__(self, n):
		self.uf = [i for i in range(n)]
		self.size = [1] * n

	def find(self, node):
		if node != self.uf[node]:
			return self.find(self.uf[node])
		else:
			return node

	def union(self, x, y):
		x_r = self.find(x)
		y_r = self.find(y)
		if x_r == y_r:
			return
		self.uf[y_r] = x_r
		self.size[x_r] += self.size[y_r]
		self.size[y_r] = 0

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def prime(n):
			cur = set()
			while n % 2 == 0:
				cur.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					cur.add(i)
					n //= i
			if n > 2:
				cur.add(n)
			return cur
		index = {A[i]: i for i in range(len(A))}
		uf = UnionFind(len(A))
		res = collections.defaultdict(list)
		for i in A:
			for j in prime(i):
				res[j].append(i)
		for (i, e) in list(res.items()):
			if e:
				root = e[0]
				for j in e[1:]:
					uf.union(index[root], index[j])
		return max(uf.size)


class DSU:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [0 for _ in range(n)]
		self.size = 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, x, y):
		(xp, yp) = (self.find(x), self.find(y))
		if xp == yp:
			return False
		if self.rank[xp] < self.rank[yp]:
			self.parent[xp] = yp
		elif self.rank[xp] > self.rank[yp]:
			self.parent[yp] = xp
		else:
			self.parent[xp] = yp
			self.rank[yp] += 1
		self.size -= 1
		return True

	def getSize(self):
		return self.size

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def getFactors(n):
			res = set()
			for i in range(2, int(sqrt(n)) + 2):
				if not n % i:
					for j in [i, n // i]:
						if j != 1:
							res.add(j)
			if not res:
				return {n}
			return res
		dsu = DSU(len(A) + 1)
		factor2Index = {}
		for (i, n) in enumerate(A):
			for factor in getFactors(n):
				if factor in factor2Index:
					dsu.union(i, factor2Index[factor])
				factor2Index[factor] = i
		groupSize = collections.defaultdict(int)
		for i in range(len(A)):
			groupSize[dsu.find(i)] += 1
		return max(groupSize.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = {}
		size = defaultdict(lambda : 1)

		def ds(a):
			while a in parent:
				a = parent[a]
			return a

		def union(a, b):
			if (a := ds(a)) != (b := ds(b)):
				if size[a] < size[b]:
					(a, b) = (b, a)
				parent[b] = a
				size[a] += size[b]
		for a in A:
			for d in factors(a):
				union(-d, a)
		return Counter((ds(a) for a in A)).most_common(1)[0][1]
FS = {}

def factors(f):
	if (n := f) not in FS:
		if n & 1:
			FS[f] = factors3(f)
		else:
			n >>= 1
			while n & 1 == 0:
				n >>= 1
			if n > 1:
				FS[f] = factors3(n) + [2]
			else:
				FS[f] = [2]
	return FS[f]

def factors3(f, start=3):
	if (n := f) not in FS:
		for i in range(start, int(sqrt(n)) + 1, 2):
			if n % i == 0:
				n = n // i
				while n % i == 0:
					n = n // i
				if n > 1:
					FS[f] = factors3(n, i + 2) + [i]
				else:
					FS[f] = [i]
				break
		else:
			FS[f] = [f]
	return FS[f]


def sieve(n):
	if n < 3:
		return
	yield 2
	p = set(range(5, n, 2))
	i = 3
	while i < n:
		yield i
		p.difference_update(list(range(i * i, n, i * 2)))
		for i in range(i + 2, n, 2):
			if i in p:
				p.remove(i)
				break
		else:
			return

class UnionFind:

	def __init__(self, n):
		self.uf = list(range(n))
		self.size = defaultdict(lambda : 1)

	def find(self, i):
		if self.uf[i] != i:
			self.uf[i] = self.find(self.uf[i])
		return self.uf[i]

	def union(self, a, b):
		(x, y) = (self.find(a), self.find(b))
		if x == y:
			return
		self.uf[x] = self.uf[y]
		self.size[y] += self.size[x]
		self.size[x] = 0
PS = []

def factors(n):
	if n % 2 == 0:
		yield 2
	while n % 2 == 0:
		n //= 2
	for i in range(3, int(n ** 0.5) + 2, 2):
		if i > n:
			break
		if n % i == 0:
			yield i
		while n % i == 0:
			n //= i
	if n > 2:
		yield n

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		u = UnionFind(len(A))
		x = {}
		for (i, a) in enumerate(A):
			for f in factors(a):
				if f in x:
					u.union(i, x[f])
				x[f] = i
		return max(u.size.values())


class DFU:

	def __init__(self, n):
		self.p = list(range(n))

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

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		self.p[xr] = yr

class Solution:

	def primes_set(self, d):
		for i in range(2, int(math.sqrt(d)) + 1):
			if d % i == 0:
				return self.primes_set(d // i) | set([i])
		return set([d])

	def largestComponentSize(self, A: List[int]) -> int:
		UF = DFU(len(A))
		primes = collections.defaultdict(list)
		for (i, d) in enumerate(A):
			primes_set = self.primes_set(d)
			for q in primes_set:
				primes[q].append(i)
		for (key, items) in list(primes.items()):
			for i in range(len(items) - 1):
				UF.union(items[i], items[i + 1])
		return max(Counter([UF.find(i) for i in range(len(A))]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def union(x, y):
			graph[find(x)] = find(y)

		def find(x):
			path = []
			while graph[x] != x:
				path.append(x)
				x = graph[x]
			for n in path:
				graph[n] = x
			return x
		graph = {}
		for (i, num) in enumerate(A):
			if num not in graph:
				graph[num] = num
			for factor in range(2, int(math.sqrt(num) + 1)):
				if num % factor == 0:
					for fac in (factor, num // factor):
						if fac == 0:
							print(num, fac)
						if fac in graph:
							union(num, graph[fac])
						else:
							graph[fac] = num
		roots = collections.defaultdict(int)
		for num in A:
			roots[find(num)] += 1
		return max(roots.values())


class DisjointSet:

	def __init__(self, size):
		self.parents = list(range(size))
		self.sizes = [1] * size

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

	def union(self, x, y):
		parent_x = self.find(x)
		parent_y = self.find(y)
		if parent_x != parent_y:
			self.sizes[parent_x] += self.sizes[parent_y]
			self.parents[parent_y] = parent_x

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		N = len(A)

		def to_divisors(n):
			if n % 6 == 0:
				return [2, 3]
			if n % 3 == 0:
				return [3]
			if n % 2 == 0:
				return [2]
			return []
		maxA = max(A)
		divisors = [to_divisors(i) for i in range(maxA + 1)]
		for i in range(4, maxA + 1):
			if len(divisors[i]) == 0:
				for j in range(i, maxA + 1, i):
					divisors[j].append(i)
		disjoint_set = DisjointSet(N)
		divisor_to_index = {}
		for (i, a) in enumerate(A):
			for d in divisors[a]:
				if d in divisor_to_index:
					disjoint_set.union(i, divisor_to_index[d])
				divisor_to_index[d] = i
		return max(disjoint_set.sizes)


class DSU:

	def __init__(self, n: int):
		self.n = n
		self.root = list(range(n))
		self.size = [1] * n
		self.max = 1

	def find(self, x: int) -> int:
		if self.root[x] != x:
			self.root[x] = self.find(self.root[x])
		return self.root[x]

	def union(self, x: int, y: int):
		(rx, ry) = (self.find(x), self.find(y))
		if not rx == ry:
			self.root[rx] = ry
			self.size[ry] += self.size[rx]
			self.max = max(self.max, self.size[ry])

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		dsu = DSU(n)
		seen = {}
		for (i, a) in enumerate(A):
			for j in range(2, int(math.sqrt(a)) + 1):
				if a % j:
					continue
				if j in seen:
					dsu.union(i, seen[j])
				else:
					seen[j] = i
				if a // j in seen:
					dsu.union(i, seen[a // j])
				else:
					seen[a // j] = i
			if a in seen:
				dsu.union(i, seen[a])
			else:
				seen[a] = i
		return dsu.max


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = max(A) + 1
		parent = [i for i in range(n)]
		rank = [0] * n
		for a in A:
			for k in range(2, int(sqrt(a)) + 1):
				if a % k == 0:
					self.union(parent, a, k, rank)
					self.union(parent, a, a // k, rank)
		counter = collections.Counter()
		for a in A:
			counter[self.find_root(parent, a)] += 1
		return max(counter.values())

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

	def union(self, parent, x, y, rank):
		x_root = self.find_root(parent, x)
		y_root = self.find_root(parent, y)
		if x_root != y_root:
			if rank[x_root] < rank[y_root]:
				parent[x_root] = y_root
			elif rank[x_root] > rank[y_root]:
				parent[y_root] = x_root
			else:
				parent[x_root] = y_root
				rank[y_root] += 1

	def find_common_factor(self, a, b):
		for i in range(2, min(a, b) + 1):
			if a % i == 0 and b % i == 0:
				return True
		return False


import math

class DSU:

	def __init__(self, N):
		self.p = list(range(N))
		self.sizes = [1] * N

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

	def union(self, x, y):
		(x_root, y_root) = (self.find(x), self.find(y))
		if x_root == y_root:
			return
		if self.sizes[x_root] > self.sizes[y_root]:
			self.p[x_root] = y_root
			self.sizes[y_root] += self.sizes[x_root]
		else:
			self.p[y_root] = x_root
			self.sizes[x_root] += self.sizes[y_root]

class Solution:

	def prime_set(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.prime_set(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A: List[int]) -> int:
		prime_map = {}
		for i in range(len(A)):
			P = self.prime_set(A[i])
			for p in P:
				if p not in prime_map:
					prime_map[p] = []
				prime_map[p].append(i)
		DSU_groups = DSU(len(A))
		for (_, group) in prime_map.items():
			for i in range(len(group) - 1):
				DSU_groups.union(group[i], group[i + 1])
		return max(DSU_groups.sizes)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		class UF:

			def __init__(self, N):
				self.parents = [i for i in range(N)]
				self.sizes = [1 for _ in range(N)]
				self.max = 1

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

			def union(self, x, y):
				x = self.find(x)
				y = self.find(y)
				if self.sizes[x] < self.sizes[y]:
					(x, y) = (y, x)
				if x != y:
					self.parents[y] = x
					self.sizes[x] += self.sizes[y]
					self.max = max(self.max, self.sizes[x])
		uf = UF(len(A))
		dic = {}
		for (i, num) in enumerate(A):
			for factor in range(2, int(math.sqrt(num) + 1)):
				if num % factor == 0:
					for fac in [factor, num // factor]:
						if fac in dic:
							uf.union(dic[fac], i)
						else:
							dic[fac] = i
			if num in dic:
				uf.union(dic[num], i)
			else:
				dic[num] = i
		return uf.max


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = [-1] * 100001

		def _find(x):
			if parent[x] == -1:
				return x
			parent[x] = _find(parent[x])
			return parent[x]

		def _union(x, y):
			xp = _find(x)
			yp = _find(y)
			if xp != yp:
				parent[yp] = xp
		for x in A:
			for i in range(2, int(sqrt(x)) + 1):
				if x % i == 0:
					_union(i, x)
					_union(x, x // i)
		cache = {}
		for x in A:
			xp = _find(x)
			cache[xp] = 1 + cache.get(xp, 0)
		print(cache)
		cache1 = sorted(list(cache.items()), key=lambda x: x[1])
		max = cache1[-1][0]
		return cache[max]


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parents = {val: val for val in A}
		sizes = {val: 1 for val in A}
		factorprez = {}
		maxsize = 0

		def union(one, two):
			r1 = findroot(one)
			r2 = findroot(two)
			if r1 == r2:
				return sizes[r1]
			(big, small) = (r1, r2) if sizes[r1] > sizes[r2] else (r2, r1)
			parents[small] = big
			sizes[big] += sizes[small]
			return sizes[big]

		def findroot(node):
			if parents[node] != node:
				node = findroot(parents[node])
			return parents[node]

		def primes_before(val):
			candidates = [True] * (val + 1)
			primes = []
			for i in range(2, len(candidates)):
				if not candidates[i]:
					continue
				primes.append(i)
				for j in range(i, val + 1, i):
					candidates[j] = False
			return primes
		primes = primes_before(100000)
		primeset = set(primes)
		for val in A:
			sval = val
			prime_idx = 0
			while sval not in primeset and primes[prime_idx] <= sval:
				if sval % primes[prime_idx] == 0:
					if primes[prime_idx] in factorprez:
						maxsize = max(maxsize, union(val, factorprez[primes[prime_idx]]))
					else:
						factorprez[primes[prime_idx]] = val
					while sval % primes[prime_idx] == 0:
						sval //= primes[prime_idx]
				prime_idx += 1
			if sval in primeset:
				if sval in factorprez:
					maxsize = max(maxsize, union(val, factorprez[sval]))
				else:
					factorprez[sval] = val
		return maxsize


class UnionFind:

	def __init__(self, N):
		self.par = list(range(N))
		self.rank = [0] * N
		self.size = [0] * N

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return
		if self.rank[px] < self.rank[py]:
			self.par[px] = py
			self.size[py] += self.size[px]
		elif self.rank[px] > self.rank[py]:
			self.par[py] = px
			self.size[px] += self.size[py]
		else:
			self.par[py] = px
			self.rank[px] += 1
			self.size[px] += self.size[py]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		N = max(A)
		primes = []
		res = 0
		for i in range(2, int(N ** 0.5) + 1):
			for j in primes:
				if i % j == 0:
					break
			else:
				primes.append(i)
		uf = UnionFind(N + 1)
		used_primes = set()
		for a in A:
			if a < 2:
				continue
			a_primes = []
			for p in primes:
				if p * p > a:
					break
				if a % p == 0:
					a_primes.append(p)
					while a % p == 0:
						a //= p
			if a > 1:
				a_primes.append(a)
			idx = uf.find(a_primes[0])
			used_primes.add(a_primes[0])
			uf.size[idx] += 1
			for i in range(1, len(a_primes)):
				uf.union(a_primes[0], a_primes[i])
		for a in used_primes:
			idx = uf.find(a)
			res = max(res, uf.size[idx])
		return res


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parents = [-1] * (max(A) + 1)

		def find(x: int) -> int:
			if parents[x] < 0:
				return x
			parents[x] = find(parents[x])
			return parents[x]

		def union(x, y):
			root_x = find(x)
			root_y = find(y)
			if root_x == root_y:
				return
			depth_x = parents[root_x]
			depth_y = parents[root_y]
			if depth_x <= depth_y:
				parents[root_y] = root_x
				if depth_x == depth_y:
					parents[root_x] -= 1
			else:
				parents[root_x] = root_y

		def get_factor(n: int) -> list:
			ans = []
			for i in range(2, int(n ** (1 / 2) + 1)):
				if n % i == 0:
					ans.append(i)
					d = n / i
					if d != i and d % 1 == 0:
						ans.append(int(d))
			return ans
		for num in A:
			fact = get_factor(num)
			for v in fact:
				union(num, v)
		group = [find(num) for num in A]
		cnt = Counter(group)
		return cnt.most_common(1)[0][1]


class UF:

	def __init__(self, n):
		self.p = [i for i in range(n)]
		self.s = [1] * n

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

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		self.s[xr] += self.s[yr]
		self.p[yr] = xr

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def add_prime(i, j, primes):
			if i not in primes:
				primes[i] = [j]
			else:
				primes[i].append(j)
		g = UF(len(A))
		primes = {}
		for (j, k) in enumerate(A):
			i = 2
			while i * i <= k:
				if k % i == 0:
					add_prime(i, j, primes)
					while k % i == 0:
						k = k // i
				i += 1
			if k > 1:
				add_prime(k, j, primes)
		for l in primes.values():
			(j, r) = (l[0], g.find(l[0]))
			for i in l[1:]:
				if g.find(i) != r:
					g.union(j, i)
		return max(g.s)


import math

class Solution:

	def __init__(self):
		self.prime_divisors_cache = {}

	def prime_divisors(self, x, i=2):
		if x in self.prime_divisors_cache:
			return self.prime_divisors_cache[x]
		while i * i <= x:
			if x % i != 0:
				i += 1
				if i > 3:
					i += 1
			else:
				self.prime_divisors_cache[x] = set([i]) | self.prime_divisors(x // i, i)
				return self.prime_divisors_cache[x]
		res = set()
		if x > 1:
			res.add(x)
		self.prime_divisors_cache[x] = res
		return self.prime_divisors_cache[x]

	def largestComponentSize(self, A: List[int]) -> int:
		parent = dict()
		size = dict()
		reps = set()

		def getRep(x):
			while parent[x] != x:
				(x, parent[x]) = (parent[x], parent[parent[x]])
			return x

		def add(x):
			parent[x] = x
			size[x] = 1
			reps.add(x)

		def merge(x, y):
			x = getRep(x)
			y = getRep(y)
			if x == y:
				return
			if size[x] < size[y]:
				(x, y) = (y, x)
			size[x] += size.pop(y)
			parent[y] = x
			reps.remove(y)
		prime2dividend = {}
		for x in A:
			add(x)
			for p in self.prime_divisors(x):
				if not p in prime2dividend:
					prime2dividend[p] = [x]
				else:
					prime2dividend[p].append(x)
		for (_, xs) in list(prime2dividend.items()):
			first = xs.pop()
			for x in xs:
				merge(first, x)
		return max([size[rep] for rep in reps])


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		ma = max(A)
		N = len(A)
		m = list(range(ma + 1))
		for a in A:
			for k in range(2, int(math.sqrt(a)) + 1):
				if a % k == 0:
					self.u(m, a, k)
					self.u(m, a, a // k)
		count = collections.defaultdict(int)
		for a in A:
			count[self.f(m, a)] += 1
		return max(count.values())

	def f(self, m, a):
		while m[a] != a:
			m[a] = m[m[a]]
			a = m[a]
		return a

	def u(self, m, a, b):
		if m[a] == m[b]:
			return
		pa = self.f(m, a)
		pb = self.f(m, b)
		m[pa] = pb


import math

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = dict()

		def find_parent(x):
			if x not in parent:
				parent[x] = -1
				return x
			if parent[x] == -1:
				return x
			parent[x] = find_parent(parent[x])
			return parent[x]

		def union_num(x, y):
			px = find_parent(x)
			py = find_parent(y)
			if px != py:
				parent[py] = px
			return
		for x in A:
			for i in range(2, int(math.sqrt(x)) + 1):
				if x % i == 0:
					union_num(i, x)
					union_num(i, x // i)
		count = 0
		count_ref = dict()
		for x in A:
			p = find_parent(x)
			count_ref[p] = count_ref.get(p, 0) + 1
			count = max(count, count_ref[p])
		return count


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		par = [-1] * 100001

		def find1(x):
			if par[x] == -1:
				return x
			par[x] = find1(par[x])
			return par[x]

		def union1(x, y):
			xp = find1(x)
			yp = find1(y)
			if xp != yp:
				par[yp] = xp
		for x in A:
			for i in range(2, int(sqrt(x)) + 1):
				if x % i == 0:
					union1(i, x)
					union1(x, x // i)
		cnt = 0
		cach = {}
		for x in A:
			xp = find1(x)
			cnt = max(cnt, 1 + cach.get(xp, 0))
			cach[xp] = 1 + cach.get(xp, 0)
		return cnt


class UF:

	def __init__(self, N):
		self.parent = [i for i in range(N)]
		self.size = [1 for i in range(N)]

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

	def union(self, X, Y):
		root_x = self.find(X)
		root_y = self.find(Y)
		if root_x != root_y:
			if self.size[root_x] >= self.size[root_y]:
				self.parent[root_y] = root_x
				self.size[root_x] += self.size[root_y]
			else:
				self.parent[root_x] = root_y
				self.size[root_y] += self.size[root_x]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		factor_map = {}
		uf = UF(len(A))
		for (index, num) in enumerate(A):
			for factor in range(2, int(sqrt(num) + 1)):
				if num % factor == 0:
					if factor_map.get(factor) is None:
						factor_map[factor] = index
					else:
						uf.union(index, factor_map[factor])
					j = num // factor
					if factor_map.get(j) is None:
						factor_map[j] = index
					else:
						uf.union(index, factor_map[j])
			if factor_map.get(num) is None:
				factor_map[num] = index
			else:
				uf.union(index, factor_map[num])
		return max(uf.size)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		from math import sqrt
		from collections import defaultdict
		initial = set(A)
		parent = defaultdict(int)
		for e in A:
			parent[e] = e

		def find(c):
			if c not in parent:
				parent[c] = c
				return c
			while parent[c] != c:
				parent[c] = parent[parent[c]]
				c = parent[c]
			return c

		def union(c1, c2):
			(p1, p2) = (find(c1), find(c2))
			if p1 == p2:
				return
			parent[p1] = p2
		for e in A:
			for n in range(2, int(sqrt(e)) + 1):
				if e % n == 0:
					union(e, e // n)
					union(e, n)
		counts = defaultdict(int)
		for k in list(parent.keys()):
			if k in initial:
				counts[find(k)] += 1
		return max(counts.values())


from collections import defaultdict

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		small_primes = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317)
		label = defaultdict(int)

		def findRoot(key):
			if label[key] > 0:
				label[key] = findRoot(label[key])
				return label[key]
			else:
				return key

		def mergeRoot(k1, k2):
			(r1, r2) = (findRoot(k1), findRoot(k2))
			if r1 != r2:
				(r1, r2) = (min(r1, r2), max(r1, r2))
				label[r1] += label[r2]
				label[r2] = r1
			return r1
		for x in A:
			root_id = 0
			t = sqrt(x) + 1
			for p in small_primes:
				if p > t:
					break
				elif x % p == 0:
					root_id = findRoot(p) if root_id == 0 else mergeRoot(root_id, p)
					while x % p == 0:
						x //= p
			if x != 1:
				root_id = findRoot(x) if root_id == 0 else mergeRoot(root_id, x)
			label[root_id] -= 1
		return -min(label.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def find(m, a):
			while m[a] != a:
				m[a] = m[m[a]]
				a = m[a]
			return a

		def union(m, a, b):
			if m[a] == m[b]:
				return
			pa = find(m, a)
			pb = find(m, b)
			m[pa] = pb
		Max = max(A)
		m = [i for i in range(Max + 1)]
		for num in A:
			for k in range(2, int(math.sqrt(num)) + 1):
				if num % k == 0:
					union(m, num, k)
					union(m, num, num // k)
		count = collections.defaultdict(int)
		for num in A:
			count[find(m, num)] += 1
		return max(count.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def find(u):
			if p[u] == -1:
				return u
			p[u] = find(p[u])
			return p[u]

		def union(u, v):
			u = find(u)
			v = find(v)
			if u != v:
				if r[u] > r[v]:
					p[v] = u
				elif r[u] < r[v]:
					p[u] = v
				else:
					p[v] = u
					r[u] += 1
		n = len(A)
		m = max(A) + 1
		p = [-1] * m
		r = [0] * m
		for i in range(n):
			factor = 2
			num = A[i]
			while num >= factor * factor:
				if num % factor == 0:
					num //= factor
					union(A[i], factor)
				else:
					factor += 1
			union(A[i], num)
		s = [0] * m
		for i in range(n):
			s[find(A[i])] += 1
		return max(s)


from collections import Counter, defaultdict

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def factorize(x):
			ret = set()
			i = 2
			while i * i <= x:
				while x % i == 0:
					ret.add(i)
					x = x // i
				i += 1
			if x != 1:
				ret.add(x)
			return ret
		factor_to_num = defaultdict(list)
		for (i, a) in enumerate(A):
			for factor in factorize(a):
				factor_to_num[factor].append(i)
		par = list(range(len(A)))
		rank = [0] * len(A)

		def find(x):
			if par[x] == x:
				return x
			else:
				ret = find(par[x])
				par[x] = ret
				return ret

		def unite(x, y):
			x = find(x)
			y = find(y)
			if x == y:
				return
			if rank[x] < rank[y]:
				par[x] = y
			else:
				par[y] = x
				if rank[x] == rank[y]:
					rank[x] += 1
		for factor in factor_to_num.keys():
			nums = factor_to_num[factor]
			for i in range(1, len(nums)):
				unite(nums[i - 1], nums[i])
		counter = Counter((find(i) for i in range(len(A))))
		return max(counter.values())


class DSU:

	def __init__(self, N):
		self.p = list(range(N))

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

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		self.p[xr] = yr

class Solution:

	def primes_set(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primes_set(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A):
		n = len(A)
		UF = DSU(n)
		primes = defaultdict(list)
		for (i, num) in enumerate(A):
			pr_set = self.primes_set(num)
			for q in pr_set:
				primes[q].append(i)
		for (_, indexes) in list(primes.items()):
			for i in range(len(indexes) - 1):
				UF.union(indexes[i], indexes[i + 1])
		return max(Counter([UF.find(i) for i in range(n)]).values())

class UnionFind:

	def __init__(self, A):
		self.factorparent = []
		for i in range(A):
			self.factorparent.append(i)

	def union(self, x, y):
		xp = self.find(x)
		yp = self.find(y)
		self.factorparent[xp] = yp

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

class Solution1:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		length = len(A)
		obj = UnionFind(length)
		primes = defaultdict(list)
		for (i, n) in enumerate(A):
			primeset = self.getPrime(n)
			for p in primeset:
				primes[p].append(i)
		for (k, v) in list(primes.items()):
			for i in range(len(v) - 1):
				obj.union(v[i], v[i + 1])
		primes = {}
		maxval = 0
		for i in range(length):
			val = obj.find(i)
			primes[val] = primes.get(val, 0) + 1
			maxval = max(maxval, primes[val])
		return maxval

	def getPrime(self, n):
		i = 2
		while i <= int(sqrt(n)):
			if n % i == 0:
				return self.getPrime(n // i) | set([i])
			i += 1
		return set([n])


class Primes:

	def __init__(self):
		M = ceil(sqrt(100000)) + 1
		isPrime = [True] * M
		k = 2
		while k < M:
			n = 2
			while k * n < M:
				isPrime[k * n] = False
				n += 1
			k += 1
			while k < M and (not isPrime[k]):
				k += 1
		self.primes = [k for k in range(2, M) if isPrime[k]]

class Solution:
	primes = Primes().primes

	def largestComponentSize(self, A: List[int]) -> int:

		def getPrimeFactors(a):
			ans = []
			for p in Solution.primes:
				if p * p > a:
					break
				if a % p == 0:
					ans.append(p)
					while True:
						a = a // p
						if a % p != 0:
							break
			if a > 1:
				ans.append(a)
			return ans
		N = len(A)
		D = defaultdict(list)
		for k in range(N):
			a = A[k]
			ap = getPrimeFactors(a)
			for p in ap:
				D[p].append(k)
		dsu = DSU(N)
		for (p, indexList) in list(D.items()):
			n = len(indexList)
			for i in range(n - 1):
				dsu.union(indexList[i], indexList[i + 1])
		return max(dsu.size)

class DSU:

	def __init__(self, size):
		self.size = [1] * (size + 1)
		self.parent = [i for i in range(size + 1)]

	def find(self, i):
		while self.parent[i] != i:
			i = self.parent[i] = self.parent[self.parent[i]]
		return i

	def union(self, i, j):
		i = self.find(i)
		j = self.find(j)
		if i == j:
			return
		if self.size[i] > self.size[j]:
			(i, j) = (j, i)
		self.parent[i] = j
		self.size[j] += self.size[i]
		return j


from math import sqrt
from collections import Counter

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = [i for i in range(len(A))]
		size = [1 for i in range(len(A))]
		primes = {}

		def find_parent(node):
			if node == parent[node]:
				return node
			parent[node] = find_parent(parent[node])
			return parent[node]

		def union(a, b):
			par_a = find_parent(a)
			par_b = find_parent(b)
			parent[par_a] = par_b

		def primes_set(n):
			for i in range(2, int(math.sqrt(n)) + 1):
				if n % i == 0:
					return primes_set(n // i) | set([i])
			return set([n])
		for (i, num) in enumerate(A):
			pr_set = primes_set(num)
			for q in pr_set:
				primes[q] = primes.get(q, []) + [i]
		for (i, nodes) in list(primes.items()):
			nodes = list(set(nodes))
			for j in range(len(nodes) - 1):
				union(nodes[j], nodes[j + 1])
		return max(Counter([find_parent(i) for i in range(len(A))]).values())


class Solution:

	def largestComponentSize(self, nums: List[int]) -> int:
		uf = {}

		def find(x):
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			uf.setdefault(x, x)
			uf.setdefault(y, y)
			uf[find(x)] = uf[find(y)]
		for num in nums:
			union(num, num)
			for i in range(2, int(math.sqrt(num)) + 1):
				if num % i == 0:
					union(num, i)
					union(num // i, i)
		group_counter = collections.Counter()
		for num in nums:
			group_counter[find(num)] += 1
		return max(group_counter.values())


class UnionFind:

	def __init__(self, nums):
		self.nums = nums
		self.groups = list(range(len(nums)))
		self.sizes = [1] * len(nums)

	def union(self, a, b):
		(a, b) = (self.find(a), self.find(b))
		if a == b:
			return
		if self.sizes[a] < self.sizes[b]:
			(a, b) = (b, a)
		self.sizes[a] += self.sizes[b]
		self.groups[b] = self.groups[a]

	def find(self, a):
		head = self.groups[a]
		while head != self.groups[head]:
			head = self.groups[head]
		node = self.groups[a]
		while node != self.groups[node]:
			(node, self.groups[node]) = (self.groups[node], head)
		return head

	def largest(self):
		return max(self.sizes)

class Solution:

	def largestComponentSize(self, a: List[int]) -> int:

		def factors(n):
			ans = {n}
			for i in range(2, int(math.sqrt(n)) + 1):
				if n % i == 0:
					ans.add(i)
					ans.add(n // i)
			return ans
		uf = UnionFind(a)
		primes = defaultdict(list)
		for (i, num) in enumerate(a):
			pr_set = factors(num)
			for prime in pr_set:
				primes[prime].append(i)
		for (prime, idxs) in primes.items():
			for i in range(len(idxs) - 1):
				uf.union(idxs[i], idxs[i + 1])
		return uf.largest()


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		graph = defaultdict(list)
		uf = UnionFind(len(A))
		for (i, num) in enumerate(A):
			prime_factors = set(self.get_prime_factors(num))
			for factor in prime_factors:
				graph[factor].append(i)
		for factor in graph:
			indices = graph[factor]
			for i in range(len(indices) - 1):
				uf.union(indices[i], indices[i + 1])
		counter = Counter()
		for i in range(len(A)):
			root = uf.find(i)
			counter[root] += 1
		return max(counter.values())

	def get_prime_factors(self, num):
		res = []
		factor = 2
		while num >= factor * factor:
			if num % factor == 0:
				res.append(factor)
				num = num // factor
			else:
				factor += 1
		res.append(num)
		return res

class UnionFind:

	def __init__(self, n):
		self.parent = list(range(n))

	def union(self, x, y):
		rootx = self.find(x)
		rooty = self.find(y)
		if rootx == rooty:
			return False
		self.parent[rooty] = rootx
		return True

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


from math import sqrt
from collections import Counter

class DisjointSet:

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

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

	def union(self, x, y):
		root1 = self.find(x)
		root2 = self.find(y)
		self.parent[root2] = root1

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		ds = DisjointSet(n)

		def prime_set(n):
			for i in range(2, int(sqrt(n)) + 1):
				if n % i == 0:
					return prime_set(n // i) | set([i])
			return set([n])
		primes = {}
		for i in range(n):
			for prime in prime_set(A[i]):
				primes[prime] = primes.get(prime, []) + [i]
		for (_, indices) in list(primes.items()):
			for i in range(len(indices) - 1):
				ds.union(indices[i], indices[i + 1])
		print(ds.parent)
		print(primes)
		return max(Counter([ds.find(i) for i in range(n)]).values())


from math import sqrt
from collections import Counter

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = {}

		def ufind(a):
			if a not in parent:
				parent[a] = a
			if a != parent[a]:
				parent[a] = ufind(parent[a])
			return parent[a]

		def uunion(a, b):
			ua = ufind(a)
			ub = ufind(b)
			parent[ua] = ub
		count = Counter()
		for x in A:
			y = 2
			factors = []
			while x >= y * y:
				if x % y == 0:
					factors.append(y)
					while x % y == 0:
						x //= y
				y += 1
			if x > 1:
				factors.append(x)
			for (a, b) in zip(factors, factors[1:]):
				uunion(a, b)
			if len(factors) > 0:
				count[factors[0]] += 1
		final_count = Counter()
		for key in count.keys():
			final_count[ufind(key)] += count[key]
		best = 0
		for key in final_count.keys():
			best = max(best, final_count[key])
		return best


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		A = sorted(A)

		def factors(a):
			fact = set()
			for i in range(2, math.isqrt(a) + 1):
				if a % i == 0:
					fact.add(i)
					fact.add(a // i)
			fact.add(a)
			return fact
		parent = [i for i in range(len(A))]
		nodes = [1] * len(A)
		rank = [1] * len(A)

		def find(a):
			if parent[a] == a:
				return a
			parent[a] = find(parent[a])
			return parent[a]

		def union(a, b):
			(pa, pb) = (find(a), find(b))
			if rank[pa] > pb:
				parent[pb] = pa
				nodes[pa] += nodes[pb]
			elif rank[pa] > pb:
				parent[pa] = pb
				nodes[pb] += nodes[pa]
			else:
				parent[pb] = pa
				nodes[pa] += nodes[pb]
				rank[pa] += 1
		m = {}
		for i in range(len(A)):
			facts = factors(A[i])
			for f in facts:
				if f in m and find(i) != find(m[f]):
					union(i, m[f])
				else:
					m[f] = i
		return max(nodes)


from collections import defaultdict, Counter

class DSU:

	def __init__(self, N):
		self.par = list(range(N))
		self.rnk = [0] * N
		self.siz = [1] * N

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

	def union(self, x, y):
		(xr, yr) = list(map(self.find, (x, y)))
		if xr == yr:
			return
		if self.rnk[xr] < self.rnk[yr]:
			(xr, yr) = (yr, xr)
		if self.rnk[xr] == self.rnk[yr]:
			self.rnk[xr] += 1
		self.par[yr] = xr
		self.siz[xr] += self.siz[yr]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		B = []
		for x in A:
			facs = []
			d = 2
			while d * d <= x:
				if x % d == 0:
					while x % d == 0:
						x //= d
					facs.append(d)
				d += 1
			if x > 1 or not facs:
				facs.append(x)
			B.append(facs)
		primes = list({p for facs in B for p in facs})
		prime_to_index = {p: i for (i, p) in enumerate(primes)}
		dsu = DSU(len(primes))
		for facs in B:
			for x in facs:
				dsu.union(prime_to_index[facs[0]], prime_to_index[x])
		count = Counter((dsu.find(prime_to_index[facs[0]]) for facs in B))
		return max(count.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind(max(A))
		for num in A:
			for factor in range(2, int(sqrt(num)) + 1):
				if num % factor == 0:
					uf.union(num, factor)
					uf.union(num, num // factor)
		res = 0
		group_count = collections.defaultdict(int)
		for num in A:
			group_id = uf.find(num)
			group_count[group_id] += 1
			res = max(res, group_count[group_id])
		return res

class UnionFind:

	def __init__(self, size):
		self.parent = [i for i in range(0, size + 1)]
		self.size = [1] * (size + 1)

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

	def union(self, x, y):
		parent_x = self.find(x)
		parent_y = self.find(y)
		if parent_x == parent_y:
			return parent_x
		if self.size[parent_x] > self.size[parent_y]:
			(parent_x, parent_y) = (parent_y, parent_x)
		self.parent[parent_x] = parent_y
		self.size[parent_y] += self.size[parent_x]
		return parent_y


class DSU:

	def __init__(self):
		self.parent = defaultdict(lambda : -1)

	def union(self, x: int, y: int):
		xSet = self.find(x)
		ySet = self.find(y)
		self.parent[xSet] = ySet

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

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		counts = Counter()
		dsu = DSU()
		for node in A:
			k = 2
			factors = []
			while k * k <= node:
				if node % k == 0:
					factors.append(k)
					while node % k == 0:
						node //= k
				k += 1
			if node > 1:
				factors.append(node)
			for (x, y) in zip(factors, factors[1:]):
				dsu.union(x, y)
			if factors:
				counts[factors[0]] += 1
		finalCounts = Counter()
		for key in counts.keys():
			finalCounts[dsu.find(key)] += counts[key]
		return max(finalCounts.values())


from collections import defaultdict

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		us = UnionSet(max(A))
		num_fac_map = dict()
		for num in A:
			primes = list(self.getPrimes(num))
			num_fac_map[num] = primes[0]
			for i in range(len(primes) - 1):
				us.union(primes[i], primes[i + 1])
		_max = 0
		most_linked_fac_map = defaultdict(int)
		for num in A:
			fac = us.find(num_fac_map[num])
			most_linked_fac_map[fac] += 1
			_max = max(_max, most_linked_fac_map[fac])
		return _max

	def getPrimes(self, num):
		primes = set()
		factor = 2
		while num >= factor * factor:
			if num % factor == 0:
				primes.add(factor)
				num //= factor
			else:
				factor += 1
		primes.add(num)
		return primes

class UnionSet:

	def __init__(self, size):
		self.factors = [i for i in range(size + 1)]
		self.size = [1] * (size + 1)

	def find(self, ix):
		while self.factors[ix] != ix:
			ix = self.factors[ix]
		return ix

	def union(self, ix1, ix2):
		(p1, p2) = (self.find(ix1), self.find(ix2))
		if p1 == p2:
			return
		if self.size[p1] > self.size[p2]:
			(p1, p2) = (p2, p1)
		self.factors[p1] = p2
		self.size[p2] += self.size[p1]


class DisjointSetUnion(object):

	def __init__(self, size):
		self.parent = [i for i in range(size + 1)]
		self.size = [1] * (size + 1)

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return px
		if self.size[px] > self.size[py]:
			(px, py) = (py, px)
		self.parent[px] = py
		self.size[py] += self.size[px]
		return py

class Solution:

	def primeDecompose(self, num):
		factor = 2
		prime_factors = []
		while num >= factor * factor:
			if num % factor == 0:
				prime_factors.append(factor)
				num = num // factor
			else:
				factor += 1
		prime_factors.append(num)
		return prime_factors

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = DisjointSetUnion(max(A))
		num_factor_map = {}
		for num in A:
			prime_factors = list(set(self.primeDecompose(num)))
			num_factor_map[num] = prime_factors[0]
			for i in range(0, len(prime_factors) - 1):
				dsu.union(prime_factors[i], prime_factors[i + 1])
		max_size = 0
		group_count = defaultdict(int)
		for num in A:
			group_id = dsu.find(num_factor_map[num])
			group_count[group_id] += 1
			max_size = max(max_size, group_count[group_id])
		return max_size


import collections

class UnionFind:

	def __init__(self, n):
		self.n = n
		self.parents = list(range(n))
		self.ranks = [0 for _ in range(n)]

	def get_root(self, x):
		if self.parents[x] == x:
			return x
		self.parents[x] = self.get_root(self.parents[x])
		return self.parents[x]

	def merge(self, x, y):
		x = self.get_root(x)
		y = self.get_root(y)
		if x != y:
			if self.ranks[x] < self.ranks[y]:
				self.parents[x] = y
			else:
				self.parents[y] = x
				if self.ranks[x] == self.ranks[y]:
					self.ranks[x] += 1

def factorize_all(n):
	factorizations = [None] * (n + 1)
	factorizations[0] = {}
	factorizations[1] = {}
	for p in range(2, n + 1):
		if factorizations[p] is None:
			for k in range(1, n // p + 1):
				if factorizations[k] is None:
					continue
				fs = factorizations[k].copy()
				if p in fs:
					fs[p] += 1
				else:
					fs[p] = 1
				factorizations[k * p] = fs
	return factorizations

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind(max(A) + 1)
		factorization = factorize_all(max(A))
		ids = dict()
		for a in A:
			if a < 2:
				continue
			factors = list(factorization[a].keys())
			ids[a] = factors[0]
			for (p0, p1) in zip(factors, factors[1:]):
				uf.merge(p0, p1)
		counter = collections.defaultdict(int)
		maxval = 0
		for a in A:
			if a < 2:
				continue
			id_ = uf.get_root(ids[a])
			counter[id_] += 1
			maxval = max(maxval, counter[id_])
		return maxval


from collections import defaultdict as dd

def find(parent, num):
	if parent[num] == -1:
		return num
	else:
		parent[num] = find(parent, parent[num])
	return parent[num]

def union(parent, u, v):
	par_u = find(parent, u)
	par_v = find(parent, v)
	if par_u != par_v:
		parent[par_v] = par_u

class Solution:

	def largestComponentSize(self, a: List[int]) -> int:
		ans = 0
		n = len(a)
		parent = [-1] * 100001
		for i in range(n):
			x = a[i]
			for j in range(2, int(x ** 0.5) + 1):
				if x % j == 0:
					union(parent, j, x)
					union(parent, x // j, x)
		count = dd(int)
		for i in range(len(a)):
			par = find(parent, a[i])
			count[par] += 1
			ans = max(ans, count[par])
		return ans


from math import sqrt

class DSU:

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

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

	def union(self, x, y):
		if self.find(x) == self.find(y):
			return
		xrank = self.rank[x]
		yrank = self.rank[y]
		if xrank < yrank:
			self.parent[self.find(x)] = self.find(y)
			self.rank[x] = self.rank[y] + 1
		else:
			self.parent[self.find(y)] = self.find(x)
			self.rank[y] = self.rank[x] + 1

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		uf = DSU(n)

		def fac(x):
			yield x
			for i in range(2, int(sqrt(x)) + 1):
				if x % i == 0:
					yield i
					yield (x // i)
		graph = {}
		for (idx, x) in enumerate(A):
			for e in fac(x):
				if e in graph:
					uf.union(idx, graph[e])
				graph[e] = idx
		ctr = collections.Counter()
		for i in range(n):
			ctr[uf.find(i)] += 1
		return ctr.most_common()[0][1]


from collections import Counter

class UnionFind:

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

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

	def union(self, x, y):
		(xp, yp) = (self.find(x), self.find(y))
		if xp == yp:
			return
		if self.ranks[xp] < self.ranks[yp]:
			self.parents[xp] = yp
		elif self.ranks[xp] > self.ranks[yp]:
			self.parents[yp] = xp
		else:
			self.parents[xp] = yp
			self.ranks[yp] += 1

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		n = max(A)
		dsu = UnionFind(n + 1)
		for a in A:
			for k in range(2, int(a ** 0.5) + 1):
				if a % k == 0:
					dsu.union(a, k)
					dsu.union(a, a // k)
		return max(Counter([dsu.find(a) for a in A]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def get_primes_set(n):
			for i in range(2, int(math.sqrt(n)) + 1):
				if n % i == 0:
					return get_primes_set(n // i) | set([i])
			return set([n])
		A = set(A)
		primes = set()
		children_of = collections.defaultdict(set)
		for a in A:
			ap = get_primes_set(a)
			prev = None
			for pr in ap:
				primes.add(pr)
				children_of[pr].add(a)
				if prev is not None:
					children_of[pr].add(prev)
					children_of[prev].add(pr)
				prev = pr
		print(children_of)
		seen = set()
		sizes = dict()
		for pr in primes:
			if pr in seen:
				continue
			sizes[pr] = 0
			to_explore = collections.deque([pr])
			while to_explore:
				curr = to_explore.popleft()
				if curr in seen:
					continue
				seen.add(curr)
				sizes[pr] += curr in A
				for child in children_of[curr]:
					to_explore.append(child)
		return max(sizes.values())


class UnionFind:

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

	def union(self, i, j):
		pi = self.parent(i)
		pj = self.parent(j)
		if pi == pj:
			return
		elif self.ranks[pi] <= self.ranks[pj]:
			self.parents[pi] = pj
			self.ranks[pj] += 1 if self.ranks[pi] == self.ranks[pj] else 0
		else:
			self.parents[pj] = pi

	def parent(self, i):
		if self.parents[i] != i:
			self.parents[i] = self.parent(self.parents[i])
		return self.parents[i]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind(max(A) + 1)
		dic = {}
		for (i, num) in enumerate(A):
			factor = self.decomp(num)
			dic[num] = factor[0]
			for i in range(0, len(factor) - 1):
				uf.union(factor[i], factor[i + 1])
		count = collections.Counter()
		for num in A:
			group_id = uf.parent(dic[num])
			count[group_id] += 1
		return max((count[i] for i in count))

	def decomp(self, num):
		factor = 2
		ans = set()
		while num >= factor * factor:
			if num % factor == 0:
				num //= factor
				ans.add(factor)
			else:
				factor += 1
		ans.add(num)
		return list(ans)


class Solution:

	def find(self, parent: List[int], x: int):
		if not parent[x] == x:
			parent[x] = self.find(parent, parent[x])
		return parent[x]

	def largestComponentSize(self, A: List[int]) -> int:
		(n, mx, res) = (0, max(A), 0)
		valtocnt = collections.Counter()
		parent = list(range(mx + 1))
		for num in A:
			for d in range(int(sqrt(num)), 1, -1):
				if num % d == 0:
					parent[self.find(parent, num)] = parent[self.find(parent, d)]
					parent[self.find(parent, num)] = parent[self.find(parent, num // d)]
		for num in A:
			valtocnt[self.find(parent, num)] += 1
			res = max(res, valtocnt[self.find(parent, num)])
		return res


class UnionFind:

	def __init__(self, n: int) -> None:
		self.parent = [i for i in range(n)]

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

	def union(self, a: int, b: int):
		self.parent[self.find(b)] = self.find(a)

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind(100001)
		for x in A:
			for i in range(2, int(sqrt(x)) + 1):
				if x % i == 0:
					uf.union(i, x)
					uf.union(x, x // i)
		count = 0
		hashMap = {}
		for x in A:
			xp = uf.find(x)
			count = max(count, 1 + hashMap.get(xp, 0))
			hashMap[xp] = 1 + hashMap.get(xp, 0)
		return count


class Node:

	def __init__(self, data):
		self.data = data
		self.p = None

class Solution:

	def find(self, node):
		if node.p == node:
			return node
		node.p = self.find(node.p)
		return node.p

	def prime(self, val, d):
		for i in range(2, int(val ** 0.5) + 1):
			if val % i == 0:
				if i not in d:
					node = Node(i)
					node.p = node
					d[i] = node
				if self.find(d[val].p) == d[val]:
					d[val].p = d[i]
				else:
					self.find(d[i]).p = self.find(d[val])
				v = val // i
				if v != i:
					if v not in d:
						node = Node(v)
						node.p = node
						d[v] = node
					self.find(d[v]).p = self.find(d[val])

	def largestComponentSize(self, A: List[int]) -> int:
		d = {}
		if not A:
			return 0
		for i in A:
			if i not in d:
				node = Node(i)
				node.p = node
				d[i] = node
			self.prime(i, d)
		fr = defaultdict(int)
		for i in A:
			fr[self.find(d[i]).data] += 1
		mx = 0
		for i in fr.values():
			mx = max(i, mx)
		return mx


class UnionFind:

	def __init__(self, N):
		self.parents = [i for i in range(N)]
		self.size = [1] * N

	def find(self, x):
		root = x
		while root != self.parents[root]:
			root = self.parents[root]
		while x != root:
			parent = self.parents[x]
			self.parents[x] = root
			x = parent
		return root

	def union(self, a, b):
		root_a = self.find(a)
		root_b = self.find(b)
		if root_a == root_b:
			return False
		if self.size[root_a] <= self.size[root_b]:
			self.parents[root_a] = root_b
			self.size[root_b] += self.size[root_a]
		else:
			self.parents[root_b] = root_a
			self.size[root_a] += self.size[root_b]
		return True

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind(max(A) + 1)
		for a in A:
			for factor in range(2, int(math.sqrt(a)) + 1):
				if a % factor == 0:
					uf.union(a, factor)
					uf.union(a, a // factor)
		group2size = defaultdict(int)
		for a in A:
			group2size[uf.find(a)] += 1
		return max(group2size.values())


class DSU:

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

	def find(self, x):
		root = x
		while root != self.parent[root]:
			root = self.parent[root]
		while x != root:
			temp = self.parent[x]
			self.parent[x] = root
			x = temp
		return root

	def union(self, x, y):
		root1 = self.find(x)
		root2 = self.find(y)
		if root1 == root2:
			return False
		if self.size[root1] > self.size[root2]:
			self.parent[root2] = root1
			self.size[root1] += self.size[root2]
		else:
			self.parent[root1] = root2
			self.size[root2] += self.size[root1]
		return True

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = DSU(100001)
		for x in A:
			for j in range(2, int(x ** 0.5) + 1):
				if x % j == 0:
					dsu.union(x, j)
					dsu.union(x, x // j)
		counter = collections.Counter()
		max_val = 0
		for x in A:
			counter[dsu.find(x)] += 1
		return counter.most_common(1)[0][1]


class DisjointSetUnion:

	def __init__(self, size):
		self.parents = [i for i in range(size + 1)]
		self.size = [1] * (size + 1)

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return px
		if self.size[px] > self.size[py]:
			(px, py) = (py, px)
		self.parents[px] = py
		self.size[py] += self.size[px]
		return py
import math
from collections import defaultdict

class Solution:

	def largestComponentSize(self, A) -> int:
		dsu = DisjointSetUnion(max(A))
		for a in A:
			for factor in range(2, int(math.sqrt(a)) + 1):
				if a % factor == 0:
					dsu.union(a, factor)
					dsu.union(a, a // factor)
		max_size = 0
		group_count = defaultdict(int)
		for a in A:
			idx = dsu.find(a)
			group_count[idx] += 1
			max_size = max(max_size, group_count[idx])
		return max_size


class UnionFind:

	def __init__(self, size):
		self.parent = [i for i in range(size + 1)]
		self.rank = [1] * (size + 1)

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

	def union(self, a, b):
		pa = self.find(a)
		pb = self.find(b)
		if pa == pb:
			return
		if self.rank[pa] > self.rank[pb]:
			self.parent[pb] = pa
		elif self.rank[pb] > self.rank[pa]:
			self.parent[pa] = pb
		else:
			self.parent[pb] = pa
			self.rank[pa] += 1
import collections

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind(max(A))
		a_to_factor = {}
		for a in A:
			factors = self.find_factors(a)
			a_to_factor[a] = factors[0]
			for i in range(0, len(factors) - 1):
				uf.union(factors[i], factors[i + 1])
		parent_to_count = collections.defaultdict(int)
		max_num = 0
		for a in A:
			parent = uf.find(a_to_factor[a])
			parent_to_count[parent] += 1
			max_num = max(max_num, parent_to_count[parent])
		return max_num

	def find_factors(self, num):
		if num == 1:
			return [1]
		i = 2
		factors = list()
		while num >= i * i:
			if num % i == 0:
				factors.append(i)
				num = num // i
			else:
				i += 1
		factors.append(num)
		return list(set(factors))


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = Disj(max(A))
		for a in A:
			for factor in range(2, int(sqrt(a)) + 1):
				if a % factor == 0:
					dsu.union(a, factor)
					dsu.union(a, a // factor)
		maxx = 0
		group_count = defaultdict(int)
		for a in A:
			group_id = dsu.find(a)
			group_count[group_id] += 1
			maxx = max(maxx, group_count[group_id])
		return maxx

class Disj(object):

	def __init__(self, size):
		self.parent = [i for i in range(size + 1)]
		self.size = [1] * (size + 1)

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return px
		if self.size[px] > self.size[py]:
			(px, py) = (py, px)
		self.parent[px] = py
		self.size[py] += self.size[px]
		return py


from collections import defaultdict

class DSU:

	def __init__(self, N):
		self.par = list(range(N))
		self.rnk = [0] * N
		self.siz = [1] * N

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

	def union(self, x, y):
		(xr, yr) = list(map(self.find, (x, y)))
		if xr == yr:
			return
		if self.rnk[xr] < self.rnk[yr]:
			(xr, yr) = (yr, xr)
		if self.rnk[xr] == self.rnk[yr]:
			self.rnk[xr] += 1
		self.par[yr] = xr
		self.siz[xr] += self.siz[yr]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def primeDecompose(num):
			factor = 2
			prime_factors = []
			while num >= factor * factor:
				if num % factor == 0:
					prime_factors.append(factor)
					num //= factor
				else:
					factor += 1
			prime_factors.append(num)
			return prime_factors
		dsu = DSU(max(A) + 1)
		num_factor_map = {}
		for num in A:
			prime_factors = list(set(primeDecompose(num)))
			num_factor_map[num] = prime_factors[0]
			for i in range(0, len(prime_factors) - 1):
				dsu.union(prime_factors[i], prime_factors[i + 1])
		max_size = 0
		group_count = defaultdict(int)
		for num in A:
			group_id = dsu.find(num_factor_map[num])
			group_count[group_id] += 1
			max_size = max(max_size, group_count[group_id])
		return max_size


class UnionFind:

	def __init__(self, length):
		self.parents = {num: num for num in range(length)}
		self.ranks = {num: 1 for num in range(length)}

	def find(self, src):
		if self.parents[src] == src:
			return src
		self.parents[src] = self.find(self.parents[src])
		return self.parents[src]

	def union(self, src, dest):
		(rootSrc, rootDest) = (self.find(src), self.find(dest))
		if rootSrc == rootDest:
			return -1
		if self.ranks[rootSrc] > self.ranks[rootDest]:
			self.parents[rootDest] = rootSrc
			self.ranks[rootSrc] += self.ranks[rootDest]
			return self.ranks[rootSrc]
		else:
			self.parents[rootSrc] = rootDest
			self.ranks[rootDest] += self.ranks[rootSrc]
			return self.ranks[rootDest]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def genPrimes(num):
			i = 2
			while i * i <= num:
				if num % i == 0:
					return set([i]) | genPrimes(num // i)
				i += 1
			return set([num])
		uf = UnionFind(len(A))
		primes = defaultdict(list)
		for (i, num) in enumerate(A):
			primesNum = genPrimes(num)
			for prime in primesNum:
				primes[prime].append(i)
		for (_, indexes) in primes.items():
			for i in range(len(indexes) - 1):
				uf.union(indexes[i], indexes[i + 1])
		return max(uf.ranks.values())


from typing import List
from math import gcd, sqrt
from collections import defaultdict

class DSU:

	def __init__(self, size):
		self.sizes = [1] * size
		self.parent = [i for i in range(size)]

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

	def union(self, u, v):
		root_u = self.find(u)
		root_v = self.find(v)
		if root_u != root_v:
			if self.sizes[root_u] < self.sizes[root_v]:
				self.parent[root_u] = root_v
				self.sizes[root_v] += self.sizes[root_u]
			else:
				self.parent[root_v] = root_u
				self.sizes[root_u] += self.sizes[root_v]

	def size(self, u):
		return self.sizes[self.find(u)]
from itertools import count

def primes():

	def _not_divisible(n):
		return lambda x: x % n > 0
	yield 2
	odd = count(3, 2)
	while True:
		n = next(odd)
		yield n
		odd = list(filter(_not_divisible(n), odd))

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = DSU(max(A) + 1)
		for x in A:
			for factor in range(2, int(sqrt(x)) + 1):
				if x % factor == 0:
					dsu.union(x, factor)
					dsu.union(x, x // factor)
		(ans, counter) = (0, defaultdict(int))
		for x in A:
			counter[dsu.find(x)] += 1
			ans = max(ans, counter[dsu.find(x)])
		return ans


from collections import Counter, defaultdict, OrderedDict, deque
from bisect import bisect_left, bisect_right
from functools import reduce, lru_cache
from typing import List
import itertools
import math
import heapq
import string
true = True
false = False
(MIN, MAX, MOD) = (-1061109567, 1061109567, 1000000007)

class UF:

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

	def merge(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return
		if self.size[px] < self.size[py]:
			self.p[px] = py
			self.size[py] += self.size[px]
		else:
			self.p[py] = px
			self.size[px] += self.size[py]

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

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UF(max(A) + 1)
		for n in A:
			for i in range(2, math.ceil(math.sqrt(n)) + 1):
				if n % i == 0:
					uf.merge(n, i)
					uf.merge(n, max(n // i, 2))
		return Counter(list(map(uf.find, A))).most_common()[0][1]
sol = Solution()
ns = [2, 3, 6, 7, 4, 12, 21, 39]
ns = [1, 2, 3, 4, 5, 6, 7, 8, 9]
ns = [32, 5, 8, 11, 13, 78, 61, 16, 83, 22, 28, 93]


from math import gcd, sqrt
from collections import defaultdict

class DSU:

	def __init__(self, size):
		self.sizes = [1] * size
		self.parent = [i for i in range(size)]

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

	def union(self, u, v):
		root_u = self.find(u)
		root_v = self.find(v)
		if root_u != root_v:
			if self.sizes[root_u] < self.sizes[root_v]:
				self.parent[root_u] = root_v
				self.sizes[root_v] += self.sizes[root_u]
			else:
				self.parent[root_v] = root_u
				self.sizes[root_u] += self.sizes[root_v]

	def size(self, u):
		return self.sizes[self.find(u)]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = DSU(max(A) + 1)
		for x in A:
			for factor in range(2, int(sqrt(x)) + 1):
				if x % factor == 0:
					dsu.union(x, factor)
					dsu.union(x, x // factor)
		(ans, counter) = (0, defaultdict(int))
		for x in A:
			counter[dsu.find(x)] += 1
			ans = max(ans, counter[dsu.find(x)])
		return ans


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = DSU(max(A))
		for num in A:
			for factor in range(2, int(sqrt(num)) + 1):
				if num % factor == 0:
					dsu.union(num, factor)
					dsu.union(num, num // factor)
		max_size = 0
		group_count = {}
		for num in A:
			group_id = dsu.find(num)
			if group_id not in group_count:
				group_count[group_id] = 0
			group_count[group_id] += 1
		return max(group_count.values())

class DSU:

	def __init__(self, size):
		self.parent = [i for i in range(size + 1)]
		self.size = [1 for i in range(size + 1)]

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return px
		if self.size[px] > self.size[py]:
			(px, py) = (py, px)
		self.parent[px] = py
		self.size[py] += self.size[px]
		return py


class UnionFind:

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

	def find(self, A):
		root = A
		while root != self.parent[root]:
			root = self.parent[root]
		while A != root:
			old_parent = self.parent[A]
			self.parent[A] = root
			A = old_parent
		return root

	def union(self, A, B):
		root_A = self.find(A)
		root_B = self.find(B)
		if root_A == root_B:
			return False
		if self.size[root_A] < self.size[root_B]:
			self.parent[root_A] = root_B
			self.size[root_B] += self.size[root_A]
		else:
			self.parent[root_B] = root_A
			self.size[root_A] += self.size[root_B]
		return True

class Solution:

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

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = UnionFind(max(A) + 1)
		for a in A:
			for factor in range(2, int(sqrt(a)) + 1):
				if a % factor == 0:
					dsu.union(a, factor)
					dsu.union(a, a // factor)
		group_count = defaultdict(int)
		for a in A:
			group_id = dsu.find(a)
			group_count[group_id] += 1
		return max(group_count.values())


from collections import defaultdict

class Solution:

	def largestComponentSize(self, a: List[int]) -> int:
		d = {}

		def find(x):
			if x != d.setdefault(x, x):
				d[x] = find(d[x])
			return d[x]

		def union(x, y):
			d[find(x)] = find(y)
		for n in a:
			for i in range(2, int(n ** 0.5) + 1):
				if n % i:
					continue
				union(n, i)
				union(n, n // i)
		counter = Counter((find(i) for i in a))
		return max(counter.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		all_sets = dsu(max(A))
		for element in A:
			for factor in range(2, int(sqrt(element)) + 1):
				if element % factor == 0:
					all_sets.union(element, factor)
					all_sets.union(element, element // factor)
		result = 0
		count = defaultdict(int)
		for element in A:
			parent_id = all_sets.find(element)
			count[parent_id] += 1
			result = max(result, count[parent_id])
		return result

class dsu:

	def __init__(self, size):
		self.parent = [x for x in range(size + 1)]
		self.size = [1 for x in range(size + 1)]

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

	def union(self, x, y):
		index_x = self.find(x)
		index_y = self.find(y)
		if index_x == index_y:
			return index_x
		if self.size[index_x] > self.size[index_y]:
			(index_x, index_y) = (index_y, index_x)
		self.parent[index_x] = index_y
		self.size[index_y] += self.size[index_x]
		return index_y


import collections
import math

class DSU:

	def __init__(self, n):
		self.par = list(range(n))

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

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		self.par[xr] = yr

class Solution:

	def sieve(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.sieve(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		dsu = DSU(n)
		primes_and_multiples = collections.defaultdict(list)
		for (i, num) in enumerate(A):
			factors = self.sieve(num)
			for factor in factors:
				primes_and_multiples[factor].append(i)
		for primes in list(primes_and_multiples.values()):
			for i in range(len(primes) - 1):
				dsu.union(primes[i], primes[i + 1])
		return max(collections.Counter([dsu.find(i) for i in range(n)]).values())


import math

class UnionFind:

	def __init__(self, size):
		self.id = [i for i in range(size)]

	def find(self, p):
		root = p
		while root != self.id[root]:
			root = self.id[root]
		while p != root:
			nxt = self.id[p]
			self.id[p] = root
			p = nxt
		return root

	def unify(self, p, q):
		root1 = self.find(p)
		root2 = self.find(q)
		if root1 == root2:
			return
		self.id[root2] = root1

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		max_val = max(A)
		uf = UnionFind(max_val + 1)
		for num in A:
			for i in range(2, int(math.sqrt(num)) + 1):
				if num % i == 0:
					uf.unify(num, i)
					uf.unify(num, num // i)
		parent_count = {}
		cur_max = 1
		for num in A:
			parent = uf.find(num)
			parent_count[parent] = 1 + parent_count.get(parent, 0)
			cur_max = max(cur_max, parent_count[parent])
		return cur_max


class UF:

	def __init__(self, n):
		self.roots = [i for i in range(n)]
		self.sz = [1 for _ in range(n)]

	def find(self, x):
		while x != self.roots[x]:
			self.roots[x] = self.roots[self.roots[x]]
			x = self.roots[x]
		return x

	def union(self, x, y):
		root_x = self.find(x)
		root_y = self.find(y)
		if self.sz[root_x] >= self.sz[root_y]:
			self.roots[root_y] = root_x
			self.sz[root_x] += self.sz[root_y]
		else:
			self.roots[root_x] = root_y
			self.sz[root_y] += self.sz[root_x]
import math
from collections import defaultdict

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def factors(num):
			factor = 2
			prime_factors = []
			while num >= factor * factor:
				if num % factor == 0:
					prime_factors.append(factor)
					num = num // factor
				else:
					factor += 1
			prime_factors.append(num)
			return prime_factors
		N = len(A)
		uf = UF(max(A) + 1)
		num_factor_map = defaultdict(int)
		for num in A:
			num_factors = factors(num)
			num_factor_map[num] = num_factors[0]
			for i in range(len(num_factors) - 1):
				uf.union(num_factors[i], num_factors[i + 1])
		counter = defaultdict(int)
		for num in A:
			counter[uf.find(num_factor_map[num])] += 1
		return max(counter.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = DSU(max(A))
		for n in A:
			for j in range(2, floor(sqrt(n)) + 1):
				if n % j == 0:
					dsu.union(n, j)
					dsu.union(n, n // j)
		maxSize = 0
		groupC = defaultdict(int)
		for n in A:
			parent = dsu.find(n)
			groupC[parent] += 1
			maxSize = max(maxSize, groupC[parent])
		return maxSize

class DSU:

	def __init__(self, largest):
		self.parent = [n for n in range(largest + 1)]
		self.sz = [1] * (largest + 1)

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

	def union(self, n1, n2):
		(xR, yR) = (self.find(n1), self.find(n2))
		if xR == yR:
			return
		if self.sz[xR] < self.sz[yR]:
			(xR, yR) = (yR, xR)
		self.parent[yR] = xR
		self.sz[yR] += self.sz[xR]

	def size(self, n):
		return self.sz[n]


from typing import Set

class myset(object):

	def __init__(self, maxi):
		self.s = [i for i in range(0, maxi + 1)]
		self.l = [1] * (maxi + 1)

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return px
		if px > py:
			(px, py) = (py, px)
		self.s[px] = self.s[py]
		self.l[py] += self.l[px]
		return py

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		d: Dict[int][int] = {}
		p: List[int] = [1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317]

		def pf(x: int) -> List[int]:
			result: Set[int] = set()
			i: int = 0
			n: int = 2
			while x >= n * n:
				if x % n == 0:
					result.add(n)
					x = x // n
				else:
					n += 1
			result.add(x)
			return list(result)
		if not A:
			return 0
		s = myset(max(A))
		mypf: List[int]
		for a in A:
			mypf = pf(a)
			print(mypf)
			d[a] = mypf[0]
			for i in range(len(mypf) - 1):
				s.union(mypf[i], mypf[i + 1])
		count = {}
		maxi: int = 0
		for a in A:
			id: int = s.find(d[a])
			if id in count:
				count[id] += 1
			else:
				count[id] = 1
			maxi = max(maxi, count[id])
		return maxi


class UnionFind:

	def __init__(self, count):
		self._parent = list(range(count))
		self._size = [1] * count

	def union(self, a, b):
		(a, b) = (self.find(a), self.find(b))
		if a == b:
			return
		if self._size[a] < self._size[b]:
			(a, b) = (b, a)
		self._parent[b] = a
		self._size[a] += self._size[b]

	def find(self, x):
		while self._parent[x] != x:
			self._parent[x] = self._parent[self._parent[x]]
			x = self._parent[x]
		return self._parent[x]

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

def prime_factors(num):
	if num < 2:
		return []
	factors = []
	for factor in range(2, int(num ** 0.5) + 1):
		if num % factor == 0:
			factors.append(factor)
			while num % factor == 0:
				num //= factor
			if num == 1:
				break
	if num > 1:
		factors.append(num)
	return factors

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		length = len(A)
		union_find = UnionFind(length)
		roots = {}
		for (index, num) in enumerate(A):
			for factor in prime_factors(num):
				if factor not in roots:
					roots[factor] = index
				union_find.union(roots[factor], index)
		return max((union_find.size(index) for index in range(length)))


import math
from collections import defaultdict

class UnionFind:

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

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

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if px == py:
			return px
		if self.size[px] > self.size[py]:
			(px, py) = (py, px)
		self.parent[px] = py
		self.size[py] += self.size[px]
		return py

class Solution:

	def largestComponentSize(self, A: list()) -> int:
		n = max(A)
		n_UnionFind = UnionFind(n + 1)
		for a in A:
			for k in range(2, int(math.sqrt(a)) + 1):
				if a % k == 0:
					n_UnionFind.union(a, k)
					n_UnionFind.union(a, a // k)
		ans = 1
		count = defaultdict(int)
		for a in A:
			count[n_UnionFind.find(a)] += 1
			ans = max(ans, count[n_UnionFind.find(a)])
		return ans


class Solution:

	def primeDecompose(self, num):
		factor = 2
		prime_factors = []
		while num >= factor * factor:
			if not num % factor:
				prime_factors.append(factor)
				num //= factor
			else:
				factor += 1
		prime_factors.append(num)
		return prime_factors

	def largestComponentSize(self, A: List[int]) -> int:
		factors = collections.defaultdict(set)
		for num in A:
			prime_factors = self.primeDecompose(num)
			for p in prime_factors:
				factors[p] |= set([num])
		primes = list(factors)
		group_id = 0
		group = {}
		prime_id = {}
		updated = set(primes)
		first_round = True
		for i in range(len(primes)):
			a = primes[i]
			if a not in factors:
				continue
			for b in list(factors):
				if b == a:
					continue
				if len(factors[b]) == 1:
					del factors[b]
				elif factors[a] & factors[b]:
					factors[a] |= factors[b]
					del factors[b]
		return len(factors[max(factors, key=lambda f: len(factors[f]))])


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		p = {}

		def find(i):
			if i not in p:
				p[i] = i
			if p[i] != i:
				p[i] = find(p[i])
			return p[i]
		for a in A:
			p[a] = a
		for a in A:
			limit = int(math.sqrt(a)) + 1
			for i in range(2, limit):
				if a % i == 0:
					pa = find(a)
					pi = find(i)
					if pa in p and pi in p:
						p[pa] = p[pi]
					pa2 = find(a)
					pi2 = find(a // i)
					if pa2 in p and pi2 in p:
						p[pa2] = p[pi2]
		c = {}
		for a in A:
			c[a] = find(a)
		ans = {}
		for (k, v) in list(c.items()):
			if v not in ans:
				ans[v] = 0
			ans[v] += 1
		return max(list(ans.values()))


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parents = list(range(max(A) + 1))

		def find(x):
			while parents[x] != x:
				parents[x] = parents[parents[x]]
				x = parents[x]
			return x

		def union(x, y):
			parents[find(x)] = parents[find(y)]
		for num in A:
			for k in range(2, int(sqrt(num)) + 1):
				if num % k == 0:
					union(num, k)
					union(num, num // k)
		counts = {}
		maxC = 0
		for num in A:
			target = find(num)
			counts[target] = counts.get(target, 0) + 1
			maxC = max(maxC, counts[target])
		return maxC


class unionfind:

	def __init__(self, size):
		self.parent = [i for i in range(size + 1)]
		self.rank = [0 for _ in range(size + 1)]

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

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if px == py:
			return px
		if self.rank[px] > self.rank[py]:
			self.parent[py] = px
			return px
		else:
			self.parent[px] = py
			if self.rank[px] == self.rank[py]:
				self.rank[py] += 1
			return py

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = unionfind(max(A))
		for i in A:
			for factor in range(2, int(sqrt(i)) + 1):
				if i % factor == 0:
					dsu.union(i, factor)
					dsu.union(i, i // factor)
		max_size = 0
		group_count = defaultdict(int)
		for a in A:
			group_id = dsu.find(a)
			group_count[group_id] += 1
			max_size = max(max_size, group_count[group_id])
		return max_size


import math

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = max(A)
		array = [0] * (n + 1)
		for i in range(n + 1):
			array[i] = i

		def find(x: int) -> int:
			if x != array[x]:
				array[x] = find(array[x])
			return array[x]

		def union(x: int, y: int):
			xp = find(x)
			yp = find(y)
			if xp != yp:
				array[yp] = xp
		length = len(A)
		for i in range(length):
			for j in range(2, int(math.sqrt(A[i])) + 1):
				if A[i] % j == 0:
					union(j, A[i])
					union(A[i], A[i] // j)
		maximum = 0
		res = {}
		for i in range(length):
			pal = find(A[i])
			maximum = max(maximum, res.get(pal, 0) + 1)
			res[pal] = res.get(pal, 0) + 1
		return maximum


import math
import collections

class Solution:

	def largestComponentSize(self, A) -> int:
		self.pre = {}
		for i in A:
			for d in range(2, int(math.sqrt(i) + 1))[::-1]:
				if i % d == 0:
					self.union(self.find(i), self.find(d))
					self.union(self.find(i), self.find(i // d))
		count = collections.defaultdict(int)
		for i in A:
			count[self.find(i)] += 1
		return max(count.values())

	def find(self, x):
		if x not in self.pre:
			self.pre[x] = x
		while self.pre[x] != x:
			self.pre[x] = self.pre[self.pre[x]]
			x = self.pre[x]
		return x

	def union(self, x, y):
		if self.pre[x] == self.pre[y]:
			return
		fx = self.find(x)
		fy = self.find(y)
		self.pre[fy] = fx


class Solution:

	def largestComponentSize(self, A: List[int], N=100001) -> int:
		m = {}
		P = [i for i in range(N)]
		L = [1] * N

		def find(x):
			P[x] = P[x] if x == P[x] else find(P[x])
			return P[x]

		def union(a, b):
			a = find(a)
			b = find(b)
			if a == b:
				return
			P[b] = a
			L[a] += L[b]
		for x in A:
			m[x] = x if x not in m else m[x]
			union(m[x], x)
			for i in range(2, floor(sqrt(x)) + 1):
				if x % i:
					continue
				j = x // i
				m[i] = x if i not in m else m[i]
				union(m[i], x)
				m[j] = x if j not in m else m[j]
				union(m[j], x)
		return max(L)


class Solution:

	def get_factors(self, n: int):
		factors = set()
		for factor in self.total_factors:
			if factor > n:
				break
			if n % factor == 0:
				factors.add(factor)
		for factor in factors:
			self.total_factors.remove(factor)
		return factors

	def get_prime_numbers(self, n_max: int):
		self.total_factors = [2, 3]
		for val in range(3, n_max // 2 + 2, 2):
			for i in range(3, int(val ** 0.5) + 2, 2):
				if val % i == 0:
					break
				elif i >= int(val ** 0.5):
					self.total_factors.append(val)

	def largestComponentSize(self, A: List[int]) -> int:
		N = max(A) + 1
		nods = {d: d for d in range(N)}

		def find(x):
			root = x
			while nods[root] != root:
				root = nods[root]
			while nods[x] != root:
				parent = nods[x]
				nods[x] = root
				x = parent
			return root

		def union(x, y):
			(rx, ry) = (find(x), find(y))
			if rx != ry:
				nods[ry] = rx
		for a in A:
			for factor in range(2, int(sqrt(a)) + 1):
				if a % factor == 0:
					union(a, factor)
					union(a, a // factor)
		counts = collections.defaultdict(int)
		for a in A:
			counts[find(a)] += 1
		print(counts)
		return max(counts.values())

	def largestComponentSize_slow(self, A: List[int]) -> int:
		A.sort()
		self.get_prime_numbers(A[-1])
		max_len = 0
		while len(A) > max_len:
			factors = self.get_factors(A[0])
			new_len = 1
			A.remove(A[0])
			while factors:
				factor = factors.pop()
				to_remove = []
				for i in range(len(A)):
					if A[i] % factor == 0:
						new_len += 1
						rest = A[i] / factor
						while rest % factor == 0:
							rest /= factor
						factors = factors | self.get_factors(rest)
						to_remove.append(i)
				A = [A[i] for i in range(len(A)) if i not in to_remove]
			max_len = max(new_len, max_len)
		return max_len


from collections import defaultdict, Counter
from functools import lru_cache
MAX_N = 100000

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		sieve = Sieve(MAX_N)
		factors = defaultdict(list)
		for x in A:
			for factor in sieve.factorize(x):
				factors[factor].append(x)
		uf = UnionFind()
		for values in list(factors.values()):
			for i in range(1, len(values)):
				uf.connect(values[i - 1], values[i])
		return max(list(Counter((uf.root(x) for x in A)).values()), default=0)

class UnionFind:

	def __init__(self):
		self.parents = {}

	def connect(self, a, b):
		if a not in self.parents:
			self.parents[a] = a
		if b not in self.parents:
			self.parents[b] = b
		root = self.root(b)
		self.parents[self.root(a)] = root
		return root

	def root(self, a):
		if a not in self.parents:
			self.parents[a] = a
			return a
		if a == self.parents[a]:
			return a
		self.parents[a] = self.root(self.parents[a])
		return self.parents[a]

class Sieve:

	def __init__(self, max_n):
		self.primes = self._compute_primes(max_n)
		self.factors = {p: [p] for p in self.primes}

	def _compute_primes(self, max_n):
		primes = list()
		sieve = [True] * (max_n + 1)
		for prime in range(2, max_n + 1):
			if not sieve[prime]:
				continue
			primes.append(prime)
			for j in range(prime + prime, max_n + 1, prime):
				sieve[j] = False
		return primes

	def factorize(self, n):
		if n in self.factors:
			return self.factors[n]
		self.factors[n] = factors = set()
		work = n
		for prime in self.primes:
			if work < prime:
				break
			if work % prime == 0:
				factors.add(prime)
				work //= prime
				factors.update(self.factorize(work))
				break
		return factors

class Graph:

	def __init__(self):
		self.adj = {}
		self.factors = set()
		self.values = set()

	def add_vertex(self, p, label):
		if p not in self.adj:
			self.adj[p] = set()
		if label == 'factor':
			self.factors.add(p)
		else:
			self.values.add(p)

	def add_factor(self, factor):
		self.add_vertex(factor, 'factor')

	def add_value(self, value):
		self.add_vertex(value, 'value')

	def connect(self, p, q):
		self.adj[p].add(q)
		self.adj[q].add(p)

	def find_largest_connected_size(self):
		seen = set()
		largest = 0
		for p in list(self.adj.keys()):
			count = self._dfs_from(p, seen)
			largest = max(largest, count)
		return largest

	def _dfs_from(self, p, seen):
		if p in seen:
			return 0
		seen.add(p)
		count = 1 if p in self.values else 0
		return count + sum((self._dfs_from(q, seen) for q in self.adj[p]))


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		parent = list(range(n + 1))

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

		def union(x, y):
			px = find(x)
			py = find(y)
			parent[px] = py
		div_bucket = collections.defaultdict(list)

		def findDivisor(num):
			if num < 2:
				return set()
			for div in range(2, int(math.sqrt(num)) + 2):
				if num % div == 0:
					return findDivisor(num // div) | {div}
			return {num}
		for i in range(n):
			div_set = set()
			div_set = findDivisor(A[i])
			for div in div_set:
				div_bucket[div].append(i)
		for (_, nums) in list(div_bucket.items()):
			for j in range(len(nums) - 1):
				union(nums[j], nums[j + 1])
		return max(collections.Counter([find(x) for x in range(n)]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		factor = {}
		dsu = DSU()

		def get_primes(num):
			primes = set()
			i = 2
			while i * i <= num:
				if num % i == 0:
					while num % i == 0:
						num = num // i
					primes.add(i)
				i += 1
			if num > 1:
				primes.add(num)
			return primes
		for num in A:
			primes = get_primes(num)
			for p in primes:
				factor.setdefault(p, num)
				if dsu.find(num) != dsu.find(factor[p]):
					dsu.union(num, factor[p])
		ans = 0
		for v in list(factor.values()):
			ans = max(dsu.count[v], ans)
		return ans

class DSU:

	def __init__(self):
		self.father = {}
		self.count = {}

	def find(self, a):
		self.father.setdefault(a, a)
		self.count.setdefault(a, 1)
		if a != self.father[a]:
			self.father[a] = self.find(self.father[a])
		return self.father[a]

	def union(self, a, b):
		_a = self.find(a)
		_b = self.find(b)
		if _a != _b:
			self.father[_a] = _b
			self.count[_b] += self.count[_a]


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = {}

		def find(a):
			if a not in parent:
				parent[a] = a
				return a
			if parent[a] == a:
				return a
			parent[a] = find(parent[a])
			return parent[a]
		for num in A:
			parent[num] = num
		for num in A:
			for i in range(2, int(sqrt(num)) + 1):
				if num % i == 0:
					parent[find(num)] = parent[find(i)]
					parent[find(num)] = parent[find(num / i)]
		count = {}
		maxi = 1
		for num in A:
			tmp = find(num)
			if tmp not in count:
				count[tmp] = 1
			else:
				count[tmp] += 1
			maxi = max(maxi, count[tmp])
		return maxi

	def largestComponentSize2(self, A: List[int]) -> int:

		def gcd(a, b):
			while b != 0:
				(a, b) = (b, a % b)
			return a
		visited = [False] * len(A)
		group = [-1] * len(A)
		stack = []
		num = 0
		maxGrp = 0
		for i in range(len(A)):
			if visited[i] == False:
				stack.append(i)
				numGrp = 0
				while len(stack) > 0:
					curr = stack.pop()
					for j in range(len(A)):
						if j == curr:
							continue
						if group[j] == -1:
							if A[curr] % 2 == A[j] % 2 == 0 or gcd(A[curr], A[j]) > 1:
								group[j] = num
								numGrp += 1
								stack.append(j)
				visited[i] = True
				maxGrp = max(maxGrp, numGrp)
				num += 1
		return maxGrp


class UF:

	def __init__(self, size):
		self.d = [i for i in range(size + 1)]

	def find(self, m):
		if self.d[m] != m:
			self.d[m] = self.find(self.d[m])
		return self.d[m]

	def union(self, m, n):
		pm = self.find(m)
		pn = self.find(n)
		self.d[pm] = pn

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UF(max(A))
		for a in A:
			for factor in range(2, int(a ** 0.5) + 1):
				if a % factor == 0:
					uf.union(a, factor)
					uf.union(a, a // factor)
		ret = 0
		C = collections.Counter()
		for a in A:
			group_id = uf.find(a)
			C[group_id] += 1
			ret = max(ret, C[group_id])
		return ret


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = [-1] * 1000001

		def find(node):
			if parent[node] == -1:
				return node
			parent[node] = find(parent[node])
			return parent[node]

		def union(X, Y):
			parentX = find(X)
			parentY = find(Y)
			if parentX != parentY:
				parent[parentY] = parentX
		for node in A:
			for i in range(2, int(sqrt(node)) + 1):
				if node % i == 0:
					union(i, node)
					union(node, node // i)
		count = 0
		d = {}
		for node in A:
			parentNode = find(node)
			count = max(count, 1 + d.get(parentNode, 0))
			d[parentNode] = 1 + d.get(parentNode, 0)
		return count


from collections import defaultdict, Counter
MAX_N = 100000

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		sieve = Sieve(MAX_N + 1)
		factors = defaultdict(list)
		for x in A:
			for factor in sieve.factorize(x):
				factors[factor].append(x)
		uf = UnionFind()
		for values in list(factors.values()):
			for i in range(1, len(values)):
				uf.connect(values[i - 1], values[i])
		return max(list(Counter((uf.root(x) for x in A)).values()), default=0)

class UnionFind:

	def __init__(self):
		self.parents = {}

	def connect(self, a, b):
		if a not in self.parents:
			self.parents[a] = a
		if b not in self.parents:
			self.parents[b] = b
		root = self.root(b)
		self.parents[self.root(a)] = root
		return root

	def root(self, a):
		if a not in self.parents:
			self.parents[a] = a
			return a
		if a == self.parents[a]:
			return a
		self.parents[a] = self.root(self.parents[a])
		return self.parents[a]

class Sieve:

	def __init__(self, limit):
		self.primes = self._compute_primes(limit)
		self.factors = {p: {p} for p in self.primes}
		self.factors[1] = set()

	def _compute_primes(self, limit):
		primes = list()
		sieve = [True] * limit
		for prime in range(2, limit):
			if not sieve[prime]:
				continue
			primes.append(prime)
			for j in range(prime + prime, limit, prime):
				sieve[j] = False
		return primes

	def factorize(self, n):
		if n in self.factors:
			return self.factors[n]
		for prime in self.primes:
			if n % prime == 0:
				factors = self.factors[n] = self.factorize(n // prime).union({prime})
				return factors
		raise ValueError(f'Value larger than max known prime: {n}')

class Graph:

	def __init__(self):
		self.adj = {}
		self.factors = set()
		self.values = set()

	def add_vertex(self, p, label):
		if p not in self.adj:
			self.adj[p] = set()
		if label == 'factor':
			self.factors.add(p)
		else:
			self.values.add(p)

	def add_factor(self, factor):
		self.add_vertex(factor, 'factor')

	def add_value(self, value):
		self.add_vertex(value, 'value')

	def connect(self, p, q):
		self.adj[p].add(q)
		self.adj[q].add(p)

	def find_largest_connected_size(self):
		seen = set()
		largest = 0
		for p in list(self.adj.keys()):
			count = self._dfs_from(p, seen)
			largest = max(largest, count)
		return largest

	def _dfs_from(self, p, seen):
		if p in seen:
			return 0
		seen.add(p)
		count = 1 if p in self.values else 0
		return count + sum((self._dfs_from(q, seen) for q in self.adj[p]))


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		(divisors, groups, sizes) = ({}, {}, {})
		for num in A:
			added = False
			for i in range(2, max(int(math.sqrt(num)) + 1, 4)):
				if num % i == 0:
					added = True
					if i not in divisors:
						divisors[i] = set()
					divisors[i].add(num)
					if (num_i := int(num / i)) > 1:
						if num_i not in divisors:
							divisors[num_i] = set()
						divisors[num_i].add(num)
			if not added:
				if num not in divisors:
					divisors[num] = set()
				divisors[num].add(num)

		def union(node1: int, node2: int) -> None:
			parent1 = find(node1)
			parent2 = find(node2)
			if parent1 == parent2:
				return
			elif parent1 < parent2:
				groups[parent2] = parent1
				sizes[parent1] = sizes[parent1] + sizes[parent2]
			else:
				groups[parent1] = parent2
				sizes[parent2] = sizes[parent1] + sizes[parent2]

		def find(node: int) -> int:
			if node not in groups:
				groups[node] = node
				sizes[node] = 1
				return node
			if groups[node] == node:
				return node
			groups[node] = find(groups[node])
			return groups[node]
		for (_, common_numbers) in list(divisors.items()):
			num1 = random.sample(common_numbers, 1)[0]
			for num2 in common_numbers:
				if num1 != num2:
					union(num1, num2)
		return max(list(sizes.values()), default=1)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = {}
		for num in A:
			parent[num] = num

		def find(a):
			if a not in parent:
				parent[a] = a
				return a
			if parent[a] == a:
				return a
			parent[a] = find(parent[a])
			return parent[a]
		for num in A:
			for i in range(2, int(sqrt(num)) + 1):
				if num % i == 0:
					parent[find(num)] = parent[find(i)]
					parent[find(num)] = parent[find(num / i)]
		count = defaultdict(int)
		maxi = 1
		for num in A:
			tmp = find(num)
			count[tmp] += 1
			maxi = max(maxi, count[tmp])
		return maxi


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		dsu = DSU()
		prime_to_index = {}
		for (i, num) in enumerate(A):
			primes = self.getPrimes(num)
			for prime in primes:
				if prime in prime_to_index:
					dsu.union(prime_to_index[prime], i)
				else:
					prime_to_index[prime] = i
		return max(dsu.count.values())

	def getPrimes(self, num):
		primes = set()
		i = 2
		while i * i <= num:
			if num % i == 0:
				while num % i == 0:
					num = num // i
				primes.add(i)
			i += 1
		if num > 1:
			primes.add(num)
		return primes

class DSU:

	def __init__(self):
		self.father = {}
		self.count = {}

	def find(self, a):
		self.father.setdefault(a, a)
		self.count.setdefault(a, 1)
		if a != self.father[a]:
			self.father[a] = self.find(self.father[a])
		return self.father[a]

	def union(self, a, b):
		_a = self.find(a)
		_b = self.find(b)
		if _a != _b:
			self.father[_a] = self.father[_b]
			self.count[_b] += self.count[_a]


class UnionFind:

	def __init__(self, maxval):
		self.arr = [i for i in range(maxval)]

	def find(self, n):
		if n != self.arr[n]:
			self.arr[n] = self.find(self.arr[n])
		return self.arr[n]

	def union(self, a, b):
		self.arr[self.find(a)] = self.arr[self.find(b)]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		maxval = max(A) + 1
		oUnionFind = UnionFind(maxval)
		for i in A:
			for j in range(2, int(math.sqrt(i)) + 1):
				if i % j == 0:
					oUnionFind.union(i, j)
					oUnionFind.union(i, i // j)
		counter = collections.defaultdict(int)
		for i in A:
			counter[oUnionFind.find(i)] += 1
		return max(list(counter.values()))


class DisjointSet:

	def __init__(self, n):
		self.set = list(range(n))

	def find(self, i):
		if self.set[i] != i:
			self.set[i] = self.find(self.set[i])
		return self.set[i]

	def union(self, i, j):
		(ii, jj) = (self.find(i), self.find(j))
		self.set[ii] = jj

class Solution:

	def primeFactors(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primeFactors(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A):
		n = len(A)
		unionFind = DisjointSet(n)
		primes = defaultdict(list)
		for (i, num) in enumerate(A):
			pr_set = self.primeFactors(num)
			for q in pr_set:
				primes[q].append(i)
		for (_, indexes) in list(primes.items()):
			for i in range(len(indexes) - 1):
				unionFind.union(indexes[i], indexes[i + 1])
		return max(Counter([unionFind.find(i) for i in range(n)]).values())


class DSU:

	def __init__(self, N):
		self.data = list(range(N))

	def union(self, x, y):
		(xp, yp) = (self.find(x), self.find(y))
		self.data[xp] = yp

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

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def primeFactors(n):
			for i in range(2, int(math.sqrt(n)) + 1):
				if n % i == 0:
					return primeFactors(n // i) | set([i])
			return set([n])
		primes = collections.defaultdict(list)
		for (i, num) in enumerate(A):
			factors = primeFactors(num)
			for factor in factors:
				primes[factor].append(i)
		dsu = DSU(len(A))
		for (factor, nums) in primes.items():
			for i in range(1, len(nums)):
				dsu.union(nums[i - 1], nums[i])
		counter = collections.Counter((dsu.find(i) for i in dsu.data))
		return max((v for v in counter.values()))


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = [-1] * 1000001

		def _find(a):
			if parent[a] == -1:
				return a
			parent[a] = _find(parent[a])
			return parent[a]

		def _union(a, b):
			ap = _find(a)
			bp = _find(b)
			if ap != bp:
				parent[bp] = ap
		for a in A:
			for i in range(2, int(sqrt(a)) + 1):
				if a % i == 0:
					_union(i, a)
					_union(a, a // i)
		cnt = 0
		tmp = {}
		for a in A:
			ap = _find(a)
			cnt = max(cnt, 1 + tmp.get(ap, 0))
			tmp[ap] = 1 + tmp.get(ap, 0)
		return cnt


class Union:

	def __init__(self, arr):
		self.weight = {}
		self.par = {}
		for a in range(1, max(arr) + 1):
			self.par[a] = a
			self.weight[a] = 1

	def find(self, a):
		while self.par[a] != a:
			a = self.par[a]
		return a

	def union(self, a, b):
		(pa, pb) = (self.find(a), self.find(b))
		if pa == pb:
			return
		if self.weight[pa] < self.weight[pb]:
			(pa, pb) = (pb, pa)
		self.weight[pa] += self.weight[pb]
		self.par[pb] = pa

	def getMaxWeight(self):
		return max(list(map(len, list(self.weight.values()))))

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		union = Union(A)
		for a in A:
			sqr = int(sqrt(a))
			for j in range(2, sqr + 1):
				if a % j == 0:
					union.union(a, a // j)
					union.union(a, j)
		groups = collections.defaultdict(int)
		for a in A:
			groups[union.find(a)] += 1
		return max(groups.values())


class UF:

	def __init__(self) -> None:
		self.parent = {}
		self.sz = {}
		self.count = 0

	def add(self, p):
		if p not in self.parent:
			self.parent[p] = p
			self.sz[p] = 1
			self.count += 1

	def find(self, p: int) -> int:
		while p != self.parent[p]:
			self.parent[p] = self.parent[self.parent[p]]
			p = self.parent[p]
		return p

	def union(self, p: int, q: int) -> None:
		i = self.find(p)
		j = self.find(q)
		if i == j:
			return
		if self.sz[i] > self.sz[j]:
			self.parent[j] = i
			self.sz[i] += self.sz[j]
		else:
			self.parent[i] = j
			self.sz[j] += self.sz[i]
		self.count -= 1

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def fac(n):
			for i in range(2, int(n ** 0.5) + 1):
				if n % i == 0:
					n //= i
					return set((i,)) | fac(n)
			return set((n,))

		@lru_cache(None)
		def group_id(p):
			return uf.find(p)
		uf = UF()
		c = Counter()
		for n in A:
			factors = fac(n)
			key = tuple(sorted(factors))
			c[key] += 1
			if c[key] == 1:
				p = factors.pop()
				uf.add(p)
				for q in factors:
					uf.add(q)
					uf.union(p, q)
		if uf.count == 1:
			return len(A)
		groups = Counter()
		for (factors, value) in c.items():
			groups[group_id(factors[0])] += value
		return groups.most_common()[0][1]


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		mp = {}
		ans = 0

		def find(a):
			if a not in mp:
				mp[a] = a
			if mp[a] != a:
				mp[a] = find(mp[a])
			return mp[a]

		def union(a, b):
			pa = find(a)
			pb = find(b)
			if pa != pb:
				mp[pa] = pb
		for a in A:
			t = int(math.sqrt(a))
			for k in range(2, t + 1):
				if a % k == 0:
					union(a, k)
					union(a, a / k)
		return collections.Counter([find(a) for a in A]).most_common(1)[0][1]


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = {}
		size = {}

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

		def union(rootlist):
			if not rootlist:
				return
			for i in range(1, len(rootlist)):
				parent[rootlist[i]] = rootlist[0]
				size[rootlist[0]] += size[rootlist[i]]
			size[rootlist[0]] += 1
		fact = [[] for _ in range(len(A))]
		for j in range(len(A)):
			(num, p) = (A[j], 2)
			while num >= p * p:
				if num % p == 0:
					fact[j].append(p)
					(size[p], parent[p]) = (0, p)
					while num % p == 0:
						num //= p
				p += 1
			if num > 1:
				fact[j].append(num)
				(size[num], parent[num]) = (0, num)
		for i in range(len(fact)):
			rootset = set()
			for factor in fact[i]:
				rootset.add(find(factor))
			union(list(rootset))
		return max(size.values())


from typing import List
from collections import defaultdict, deque
from math import sqrt

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		factors = defaultdict(set)
		disjoint = list(range(len(A)))

		def populateFactors():
			for i in range(len(A)):
				a = A[i]
				if a == 1:
					continue
				x = a
				while x % 2 == 0:
					factors[2].add(i)
					x //= 2
				for n in range(3, int(sqrt(x) + 1), 2):
					while x % n == 0:
						factors[n].add(i)
						x //= n
						if x <= 1:
							break
				if x > 1:
					factors[x].add(i)

		def find(i):
			while disjoint[i] != i:
				i = disjoint[i]
			return i

		def union(i, j):
			disjoint[find(j)] = find(i)
		populateFactors()
		for factor in factors:
			x = None
			for i in factors[factor]:
				if x is None:
					x = i
				union(x, i)
		count = defaultdict(int)
		for i in range(len(A)):
			count[find(i)] += 1
		return max(count.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = dict()

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

		def union(x, y):
			px = find(x)
			py = find(y)
			parent[px] = py
		visited = set()
		graph = collections.defaultdict(set)
		count = 0
		for a in A:
			for fact in range(2, int(sqrt(a)) + 1):
				if a % fact == 0:
					x = a
					y = fact
					z = a // fact
					px = find(a)
					py = find(y)
					pz = find(z)
					if px != py:
						union(x, y)
					if px != pz:
						union(x, z)
		mem = collections.Counter()
		for item in A:
			p = find(item)
			mem[p] += 1
		maxVal = mem.most_common()
		return maxVal[0][1]


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if len(A) <= 1:
			return len(A)
		maxA = max(A)
		unionL = list(range(maxA + 1))
		size = [1] * (maxA + 1)

		def findRoot(i):
			k1 = i
			while unionL[k1] != k1:
				unionL[k1] = unionL[unionL[k1]]
				k1 = unionL[k1]
			return k1

		def union(x, y):
			k1 = findRoot(x)
			k2 = findRoot(y)
			if k1 != k2:
				if size[k1] < size[k2]:
					unionL[k1] = k2
					size[k2] += size[k1]
				else:
					unionL[k2] = k1
					size[k1] += size[k2]
			return
		for item in A:
			mid = int(math.sqrt(item)) + 1
			for k in range(2, mid + 1):
				if item % k == 0:
					union(item, k)
					if item // k != 1:
						union(item, item // k)
		count = {}
		for item in A:
			root = findRoot(item)
			if root in count:
				count[root] += 1
			else:
				count[root] = 1
		return max(count.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		A_max = max(A)
		primes = []
		seive = [True] * (int(sqrt(A_max)) + 1)
		seive[:2] = [False, False]
		for i in range(len(seive)):
			if seive[i]:
				primes.append(i)
				for j in range(i + i, len(seive), i):
					seive[j] = False
		graph = defaultdict(list)
		for (i, num) in enumerate(A):
			for p in primes:
				if p * p > num:
					break
				if num % p == 0:
					while num % p == 0:
						num //= p
					graph[p].append(i)
			if num > 1:
				graph[num].append(i)
		print(graph)
		uf = DS(len(A))
		for indx in list(graph.values()):
			for i in range(1, len(indx)):
				uf.union(indx[i - 1], indx[i])
		parents = [uf.find(i) for i in range(len(A))]
		return max(Counter(parents).values())

class DS:

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

	def find(self, x):
		if self.p[x] >= 0:
			self.p[x] = self.find(self.p[x])
			return self.p[x]
		return x

	def union(self, x, y):
		(x, y) = (self.find(x), self.find(y))
		if x == y:
			return
		if self.p[x] < self.p[y]:
			self.p[x] -= 1
			self.p[y] = x
		else:
			self.p[y] -= 1
			self.p[x] = y


class unionfind:

	def __init__(self, N):
		self.parents = list(range(N))
		self.size = [1] * N

	def find(self, x):
		while x != self.parents[x]:
			x = self.parents[x]
		return x

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px != py:
			(sizex, sizey) = (self.size[px], self.size[py])
			if sizex < sizey:
				self.parents[px] = py
				self.size[py] += sizex
			else:
				self.parents[py] = px
				self.size[px] += sizey
		else:
			return

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		factor_dic = collections.defaultdict(int)
		uf = unionfind(len(A))
		for (idx, a) in enumerate(A):
			for factor in range(2, int(a ** 0.5) + 1):
				if a % factor == 0:
					for fac in [factor, a // factor]:
						if fac not in factor_dic:
							factor_dic[fac] = idx
						else:
							uf.union(idx, factor_dic[fac])
			if a not in factor_dic:
				factor_dic[a] = idx
			else:
				uf.union(idx, factor_dic[a])
		return max(uf.size)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = [-1] * 100001

		def _find(x):
			if parent[x] == -1:
				return x
			parent[x] = _find(parent[x])
			return parent[x]

		def _union(x, y):
			x_parent = _find(x)
			y_parent = _find(y)
			if x_parent != y_parent:
				parent[y_parent] = x_parent
		for x in A:
			for i in range(2, int(sqrt(x)) + 1):
				if x % i == 0:
					_union(i, x)
					_union(x, x // i)
		count = 0
		cache = {}
		for x in A:
			xp = _find(x)
			count = max(count, 1 + cache.get(xp, 0))
			cache[xp] = 1 + cache.get(xp, 0)
		return count


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = [-1] * 100001

		def find(x):
			if parent[x] == -1:
				return x
			parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			(xp, yp) = (find(x), find(y))
			if xp != yp:
				parent[yp] = xp
		for x in A:
			for i in range(2, int(sqrt(x)) + 1):
				if x % i == 0:
					union(i, x)
					union(x, x // i)
		count = 0
		cache = dict()
		for x in A:
			xp = find(x)
			count = max(count, 1 + cache.get(xp, 0))
			cache[xp] = 1 + cache.get(xp, 0)
		return count

		def gcd(a, b):
			if b == 0:
				return a
			return gcd(b, a % b)
		graph = dict()
		for a in A:
			graph[a] = list()
		n = len(A)
		for i in range(n - 1):
			for j in range(i + 1, n):
				(a, b) = (A[i], A[j])
				if gcd(a, b) > 1:
					graph[a].append(b)
		for a in graph.keys():
			print(f'graph[{a}]', graph[a])
		largest = float('-inf')

		def dfs(graph, node, count):
			nonlocal largest
			print('node', node, 'count', count, 'largest', largest)
			if not graph[node]:
				largest = max(largest, count)
				return
			for c in graph[node]:
				dfs(graph, c, count + 1)
		for a in A:
			dfs(graph, a, 1)
		print(largest)
		print('-' * 50)


class UnionFindSet:

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

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return False
		if self.rank[px] < self.rank[py]:
			self.parants[px] = py
		elif self.rank[px] > self.rank[py]:
			self.parants[py] = px
		else:
			self.parants[py] = px
			self.rank[py] += 1

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		s = UnionFindSet(max(A) + 1)
		for x in A:
			for i in range(2, int(math.sqrt(x)) + 1):
				if x % i == 0:
					s.union(x, i)
					s.union(x, x // i)
		hash = defaultdict(int)
		for x in A:
			hash[s.find(x)] += 1
		return max(hash.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		fc = DisjointSetUnion(max(A))
		for a in A:
			for i in range(2, int(sqrt(a)) + 1):
				if a % i == 0:
					fc.union(a, i)
					fc.union(a, a // i)
		d = collections.defaultdict(int)
		maxlen = 0
		for a in A:
			group = fc.find(a)
			d[group] += 1
			maxlen = max(maxlen, d[group])
		return maxlen

class DisjointSetUnion(object):

	def __init__(self, n):
		self.parent = [i for i in range(n + 1)]
		self.size = [1] * (n + 1)

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return px
		if self.size[px] > self.size[py]:
			(px, py) = (py, px)
		self.parent[px] = py
		self.size[py] += self.size[px]
		return py


from math import sqrt, floor
from collections import Counter

class UnionFind:

	def __init__(self, size: int) -> None:
		self.cache = list(range(size + 1))

	def find(self, val: int) -> int:
		if self.cache[val] != val:
			self.cache[val] = self.find(self.cache[val])
		return self.cache[val]

	def union(self, x: int, y: int) -> None:
		self.cache[self.find(x)] = self.cache[self.find(y)]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		union_find = UnionFind(100000)
		for num in A:
			for factor in range(2, floor(sqrt(num)) + 1):
				if num % factor == 0:
					union_find.union(num, factor)
					union_find.union(num, num // factor)
		counter = Counter(map(union_find.find, A))
		return counter.most_common(1)[0][1]


class DisjointSets:

	def __init__(self, n: int):
		self.p = n * [-1]
		self.s = n * [1]

	def find(self, i: int) -> int:
		r = i
		while self.p[r] != -1:
			r = self.p[r]
		while i != r:
			(self.p[i], i) = (r, self.p[i])
		return r

	def merge(self, i: int, j: int) -> int:
		i = self.find(i)
		j = self.find(j)
		if i != j:
			if self.s[i] < self.s[j]:
				(i, j) = (j, i)
			self.p[j] = i
			self.s[i] += self.s[j]
		return i

class Solution:

	def largestComponentSize(self, a: List[int]) -> int:
		(n, m) = (len(a), max(a))
		acnt = (m + 1) * [0]
		for ai in a:
			acnt[ai] += 1
		acnt = list(accumulate(acnt))
		ainv = n * [0]
		for i in range(n - 1, -1, -1):
			acnt[a[i]] -= 1
			ainv[acnt[a[i]]] = i
		acnt = acnt[1:] + [n]
		djs = DisjointSets(n)
		isp = (m + 1) * [True]
		for i in range(2, m + 1):
			if not isp[i]:
				continue
			p = -1
			for j in range(i, m + 1, i):
				isp[j] = False
				for k in ainv[acnt[j - 1]:acnt[j]]:
					if p >= 0:
						djs.merge(p, k)
					p = k
		return max(djs.s)


primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313]

def prime_factors(n: int) -> List[int]:
	if n == 1:
		return []
	for p in primes:
		if n % p == 0:
			return [p] + prime_factors(n // p)
	return [n]

def group_by_factors(A):
	groups = defaultdict(set)
	for a in A:
		for p in prime_factors(a):
			groups[p].add(a)
	return list(groups.values())

def adjacencies_by_intersection(gs):
	adj = [[] for _ in range(len(gs))]
	for x in range(len(gs)):
		for y in range(x):
			if gs[x] & gs[y]:
				adj[x].append(y)
				adj[y].append(x)
	return adj

def bfs(gs, adj, target):
	unvisited = set(range(len(gs)))
	largest = 0
	while unvisited:
		v = unvisited.pop()
		q = [v]
		group = set()
		while q:
			n = q.pop()
			group.add(n)
			for x in adj[n]:
				if x in unvisited:
					unvisited.remove(x)
					q.append(x)
		largest = max(largest, len(set((n for i in group for n in gs[i]))))
		if largest >= target:
			return largest
	return largest

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		gs = [g for g in group_by_factors(A) if len(g) > 1]
		adj = adjacencies_by_intersection(gs)
		target = len(A) // 2
		return bfs(gs, adj, target)


class DSU:

	def __init__(self, N):
		self.p = list(range(N))

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

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		self.p[xr] = yr

class Solution:

	def primes_set(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self.primes_set(n // i) | set([i])
		return set([n])

	def largestComponentSize2(self, A):
		n = len(A)
		UF = DSU(n)
		primes = defaultdict(list)
		for (i, num) in enumerate(A):
			pr_set = self.primes_set(num)
			for q in pr_set:
				primes[q].append(i)
		for (_, indexes) in list(primes.items()):
			for i in range(len(indexes) - 1):
				UF.union(indexes[i], indexes[i + 1])
		return max(Counter([UF.find(i) for i in range(n)]).values())

	def largestComponentSize1(self, A: List[int]) -> int:
		g = set(range(len(A)))
		r = 0
		while g:
			gc = A[g.pop()]
			ri = 1
			while True:
				gm = set()
				gc2 = 1
				for i in g:
					if gcd(A[i], gc) > 1:
						ri += 1
						gm.add(i)
						gc2 *= A[i]
				if not gm:
					break
				g -= gm
				gc = gc2
			r = max(r, ri)
		return r

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

	def largestComponentSize(self, A: List[int]) -> int:
		self.p = list(range(len(A)))

		def factors(n: int) -> set:
			return set((factor for i in range(2, int(n ** 0.5) + 1) if n % i == 0 for factor in (i, n // i)))
		d = {}
		g = set(range(len(A)))
		fx = []
		for (i, v) in enumerate(A):
			f = factors(v)
			f.add(v)
			fx += [f]
			for fi in f:
				l = d.setdefault(fi, [])
				l += [i]
		for di in list(d.values()):
			for (a, b) in zip(di[1:], di):
				self.p[self.find(a)] = self.find(b)
		return max(Counter((self.find(i) for i in self.p)).values())
		r = 0
		while g:
			gi = [g.pop()]
			g1 = [gi]
			while gi:
				gii = gi.pop()
				for f in fx[gii]:
					for di in d[f]:
						if di in g:
							g.remove(di)
							g1 += [di]
							gi += [di]
			r = max(r, len(g1))
		return r


class Solution:

	def __init__(self):
		self.arr = []

	def fac(self, n):
		for i in range(2, floor(sqrt(n) + 1)):
			if n % i == 0:
				self.union(n, i)
				self.union(n, n // i)

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

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		self.arr[xr] = yr

	def largestComponentSize(self, A: List[int]) -> int:
		self.arr = [0] * (max(A) + 1)
		ans = [0] * (max(A) + 1)
		A.sort()
		for (j, i) in enumerate(self.arr):
			self.arr[j] = j
		for i in A:
			self.fac(i)
		for i in A:
			ans[self.find(i)] += 1
		return max(ans)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def prime_factors(num):
			pfactors = []
			factor = 2
			while num >= factor * factor:
				if num % factor == 0:
					pfactors.append(factor)
					num = num // factor
				else:
					factor += 1
			pfactors.append(num)
			return pfactors

		class DisjointSetUnion(object):

			def __init__(self, n):
				self.parent = {i: i for i in range(n + 1)}
				self.size = [1] * (1 + n)

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

			def union(self, a, b):
				x = self.find(a)
				y = self.find(b)
				if x == y:
					return x
				if self.size[x] > self.size[y]:
					self.parent[y] = x
					self.size[x] += self.size[y]
					return x
				self.parent[x] = y
				self.size[y] += self.size[x]
				return y
		DS = DisjointSetUnion(max(A))
		num_id = defaultdict(int)
		for num in A:
			pf = list(set(prime_factors(num)))
			num_id[num] = pf[0]
			for i in range(len(pf) - 1):
				DS.union(pf[i], pf[i + 1])
		max_size = 0
		group_count = defaultdict(int)
		for num in A:
			group_id = DS.find(num_id[num])
			group_count[group_id] += 1
			max_size = max(max_size, group_count[group_id])
		return max_size


class Solution:

	def _factorize(self, n):
		for i in range(2, int(math.sqrt(n)) + 1):
			if n % i == 0:
				return self._factorize(n // i) | set([i])
		return set([n])

	def largestComponentSize(self, A: List[int]) -> int:
		primes = set()
		factors = {}
		for x in A:
			f = self._factorize(x)
			primes |= f
			factors[x] = list(f)
		uf = UF(primes, A)
		for x in A:
			for j in range(len(factors[x])):
				uf.union(x, factors[x][j])
			uf.sz[uf.root(x)] += 1
		return max([v for (_, v) in uf.sz.items()])

class UF:

	def __init__(self, primes, A):
		self.parent = {p: p for p in primes}
		for p in A:
			self.parent[p] = p
		self.sz = {p: 0 for p in primes}
		for p in A:
			self.sz[p] = 0

	def root(self, u):
		while self.parent[u] != u:
			self.parent[u] = self.parent[self.parent[u]]
			u = self.parent[u]
		return u

	def union(self, u, v):
		r_u = self.root(u)
		r_v = self.root(v)
		if r_u == r_v:
			return
		if self.sz[r_u] > self.sz[r_v]:
			self.parent[r_v] = r_u
			self.sz[r_u] += self.sz[r_v]
		else:
			self.parent[r_u] = r_v
			self.sz[r_v] += self.sz[r_u]


class Solution:

	def find_common_fractor(self, num: int, u):
		for i in range(2, int(sqrt(num)) + 1):
			if num % i == 0:
				u.union(num, i)
				u.union(num, num // i)

	def largestComponentSize(self, A: List[int]) -> int:
		u = UnionFind(max(A) + 1)
		for item in A:
			self.find_common_fractor(item, u)
		o = 1
		temp_dict = {}
		for item in A:
			parent = u.find(item)
			if parent not in temp_dict:
				temp_dict[parent] = 1
			else:
				temp_dict[parent] += 1
			o = max(o, temp_dict[parent])
		return o

class UnionFind:

	def __init__(self, len_: int):
		self.lst = [i for i in range(len_)]

	def find(self, num: int):
		if num != self.lst[num]:
			self.lst[num] = self.find(self.lst[num])
		return self.lst[num]

	def union(self, x: int, y: int):
		self.lst[self.find(x)] = self.lst[self.find(y)]


class UnionFind:

	def __init__(self, N):
		self.N = N
		self.rank = [1 for i in range(N)]
		self.parent = [i for i in range(N)]

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

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if px == py:
			return False
		if self.rank[px] < self.rank[py]:
			self.parent[px] = py
		else:
			self.parent[py] = px
			if self.rank[px] == self.rank[py]:
				self.rank[px] += 1
		return True

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def union_all(x):
			for i in range(2, int(x ** 0.5) + 1):
				if x % i == 0:
					uf.union(x, i)
					uf.union(x, x // i)
		uf = UnionFind(100001)
		max_size = 1
		for i in range(len(A)):
			union_all(A[i])
		d = Counter()
		for i in range(len(A)):
			d[uf.find(A[i])] += 1
			max_size = max(max_size, d[uf.find(A[i])])
		return max_size


class UnionFind:

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

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

	def union(self, i, j):
		pi = self.find(i)
		pj = self.find(j)
		if pi != pj:
			self.parent[max(pi, pj)] = min(pi, pj)
			self.size[min(pi, pj)] += self.size[max(pi, pj)]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def decompose(num):
			if num == 1:
				return []
			res = []
			remain = num
			for factor in range(2, int(math.sqrt(num)) + 1):
				if remain % factor == 0:
					while remain % factor == 0:
						remain //= factor
					res.append(factor)
			if remain > 1:
				res.append(remain)
			return res
		union_find = UnionFind(len(A))
		factor_index = dict()
		for (idx, num) in enumerate(A):
			factors = decompose(num)
			for factor in factors:
				if factor not in factor_index:
					factor_index[factor] = idx
				else:
					union_find.union(factor_index[factor], idx)
		return max(union_find.size)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind(max(A))
		for a in A:
			for factor in range(2, int(sqrt(a)) + 1):
				if a % factor == 0:
					uf.union(a, factor)
					uf.union(a, a // factor)
		count_ = defaultdict(int)
		out = 0
		for a in A:
			groupid = uf.find(a)
			count_[groupid] += 1
			out = max(out, count_[groupid])
		return out

class UnionFind:

	def __init__(self, size):
		self.parent = [i for i in range(size + 1)]
		self.size = [1] * (size + 1)

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if self.size[px] > self.size[py]:
			(px, py) = (py, px)
		self.parent[px] = py
		self.size[py] += self.size[px]


import collections
import math

class UF:

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

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px != py:
			(size_x, size_y) = (self.size[px], self.size[py])
			if size_x < size_y:
				self.parent[px] = py
				self.size[py] += size_x
			else:
				self.parent[py] = px
				self.size[px] += size_y

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		factor_to_num_index = collections.defaultdict(int)
		uf = UF(len(A))
		for (ind, num) in enumerate(A):
			for factor in range(2, int(math.sqrt(num) + 1)):
				if num % factor == 0:
					for fac in (factor, num // factor):
						if fac in factor_to_num_index:
							uf.union(ind, factor_to_num_index[fac])
						else:
							factor_to_num_index[fac] = ind
			if num not in factor_to_num_index:
				factor_to_num_index[num] = ind
			else:
				uf.union(ind, factor_to_num_index[num])
		return max(uf.size)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0

		def findPrimes(n):
			for i in range(2, int(n ** 0.5) + 1):
				if n % i == 0:
					return set([i]) | findPrimes(n // i)
			return set([n])
		findset = list(range(len(A)))

		def find(i):
			while findset[i] != i:
				i = findset[i]
			return i

		def union(i, j):
			(ri, rj) = (find(i), find(j))
			findset[rj] = ri
		primdic = defaultdict(list)
		for (i, num) in enumerate(A):
			ps = findPrimes(num)
			for p in list(ps):
				primdic[p] += (i,)
		for idxs in list(primdic.values()):
			for i in range(len(idxs) - 1):
				union(idxs[i], idxs[i + 1])
		return max(Counter((find(i) for i in range(len(A)))).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		mem = {}

		def getFactors(num: int) -> set:
			if num in mem:
				return mem[num]
			for divBy in range(2, floor(sqrt(num)) + 1):
				if num % divBy == 0:
					mem[num] = getFactors(num // divBy) | set([divBy])
					return mem[num]
			mem[num] = set([num])
			return mem[num]
		groups = {}
		factorToNum = {}
		numToGroupKey = {}
		groupKeyToNums = defaultdict(lambda : [])

		def findGroupsForFactors(factors: List[int]) -> List[int]:
			keys = set()
			for factor in factors:
				if factor in factorToNum:
					keys.add(numToGroupKey[factorToNum[factor]])
			return keys
		maxSize = 0
		for num in A:
			factors = getFactors(num)
			groupKeys = findGroupsForFactors(factors)
			for factor in factors:
				factorToNum[factor] = num
			size = 1 + sum([groups[key] for key in groupKeys])
			if len(groupKeys) >= 2:
				numToGroupKey[num] = num
				groupKeyToNums[num] = [num]
				for key in groupKeys:
					for lastNum in groupKeyToNums[key]:
						numToGroupKey[lastNum] = num
						groupKeyToNums[num].append(lastNum)
					groupKeyToNums[num].append(key)
					del groupKeyToNums[key]
					del groups[key]
				groups[num] = size
			elif len(groupKeys) == 1:
				otherGroup = list(groupKeys)[0]
				numToGroupKey[num] = otherGroup
				groupKeyToNums[otherGroup].append(num)
				groups[otherGroup] = size
			else:
				numToGroupKey[num] = num
				groupKeyToNums[num] = [num]
				groups[num] = size
			maxSize = max(maxSize, size)
		return maxSize


import math

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = [-1] * 100001

		def find(val, parent):
			if parent[val] == -1:
				return val
			parent[val] = find(parent[val], parent)
			return parent[val]

		def union(x, y, parent):
			xp = find(x, parent)
			yp = find(y, parent)
			if xp != yp:
				parent[yp] = xp
		for val in A:
			for i in range(2, int(math.sqrt(val)) + 1):
				if val % i == 0:
					union(i, val, parent)
					union(val, val // i, parent)
		c = 0
		mp = {}
		for val in A:
			pval = find(val, parent)
			c = max(c, 1 + mp.get(pval, 0))
			mp[pval] = mp.get(pval, 0) + 1
		return c


from typing import Dict

class Solution:

	def _ds_find(ds: Dict[int, int], x: int) -> int:
		if ds.setdefault(x, x) != x:
			ds[x] = Solution._ds_find(ds, ds[x])
		return ds[x]

	def largestComponentSize(self, A: List[int]) -> int:
		ds = {}
		for x in A:
			for i in range(2, int(sqrt(x)) + 1):
				if x % i == 0:
					ds[Solution._ds_find(ds, i)] = Solution._ds_find(ds, x)
					ds[Solution._ds_find(ds, i)] = Solution._ds_find(ds, x // i)
		return max(Counter((Solution._ds_find(ds, i) for i in A)).values())


class UnionFind:

	def __init__(self, n):
		self.parent = [i for i in range(n + 1)]
		self.size = [1 for i in range(n + 1)]

	def find(self, u):
		while u != self.parent[u]:
			self.parent[u] = self.parent[self.parent[u]]
			u = self.parent[u]
		return u

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

class Solution:

	def sharecommon(self, a, b):
		for k in range(2, min(a, b) + 1):
			if a % k == 0 and b % k == 0:
				return True
		return False

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		ufs = UnionFind(max(A))
		foundSet = collections.defaultdict(int)
		for a in A:
			for factor in range(2, int(sqrt(a)) + 1):
				if a % factor == 0:
					ufs.union(a, factor)
					ufs.union(a, a // factor)
		for a in A:
			foundSet[ufs.find(a)] += 1
		return max(foundSet.values()) if foundSet else 1


class Solution:

	def primeDecompose(self, num):
		factor = 2
		prime_factors = []
		while num >= factor * factor:
			if num % factor == 0:
				prime_factors.append(factor)
				num = num // factor
			else:
				factor += 1
		prime_factors.append(num)
		return prime_factors

	def largestComponentSize(self, A: List[int]) -> int:
		factorMap = {}

		def find(a):
			if a not in factorMap or factorMap[a] == a:
				factorMap[a] = a
				return a
			else:
				return find(factorMap[a])
		factorCount = {}
		maxCount = 0
		for n in A:
			primeFactors = self.primeDecompose(n)
			pivot = find(primeFactors[0])
			if pivot not in factorCount:
				factorCount[pivot] = 0
			factorCount[pivot] += 1
			for i in range(1, len(primeFactors)):
				root = find(primeFactors[i])
				factorMap[root] = pivot
				if root in factorCount and root != pivot:
					factorCount[pivot] += factorCount[root]
			maxCount = max(maxCount, factorCount[pivot])
		return maxCount


def union(parent, rank, i, j):
	parI = find(parent, i)
	parJ = find(parent, j)
	if parI == parJ:
		return
	if rank[parI] < rank[parJ]:
		parent[parI] = parJ
	elif rank[parI] > rank[parJ]:
		parent[parJ] = parI
	else:
		parent[parJ] = parI
		rank[parI] += 1

def find(parent, i):
	if i != parent[i]:
		parent[i] = find(parent, parent[i])
	return parent[i]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		rank = [0] * n
		parent = list(range(n))
		factorToSet = {}
		for (i, num) in enumerate(A):
			for factor in range(2, int(math.sqrt(num) + 1)):
				if num % factor == 0:
					if factor in factorToSet:
						union(parent, rank, i, factorToSet[factor])
					else:
						factorToSet[factor] = i
					cfactor = num // factor
					if cfactor in factorToSet:
						union(parent, rank, i, factorToSet[cfactor])
					else:
						factorToSet[cfactor] = i
			if num in factorToSet:
				union(parent, rank, i, factorToSet[num])
			else:
				factorToSet[num] = i
		for i in range(n):
			find(parent, i)
		return max(collections.Counter(parent).values())


from math import sqrt
from collections import defaultdict

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		union = DisjoinSet(max(A))
		for a in A:
			for factor in range(2, int(sqrt(a)) + 1):
				if a % factor == 0:
					union.union(a, factor)
					union.union(a, a // factor)
		result = 0
		counter = defaultdict(int)
		for i in A:
			parent = union.find(i)
			counter[parent] += 1
			result = max(result, counter[parent])
		return result

class DisjoinSet:

	def __init__(self, size):
		self.parent = [i for i in range(size + 1)]
		self.size = [1 for _ in range(size + 1)]

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

	def union(self, i, j):
		(parentI, parentJ) = (self.find(i), self.find(j))
		if parentI == parentJ:
			return
		if self.size[parentI] >= self.size[parentJ]:
			(big, small) = (parentI, parentJ)
		else:
			(big, small) = (parentJ, parentI)
		self.size[big] += self.size[small]
		self.parent[small] = big


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		parent = [i for i in range(max(A) + 1)]

		def find(x):
			if parent[x] == x:
				return x
			parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			px = find(x)
			py = find(y)
			if px == py:
				return px
			parent[py] = px
			return px
		for a in A:
			for k in range(2, int(sqrt(a)) + 1, 1):
				if a % k == 0:
					union(a, k)
					union(a, a // k)
		max_len = 0
		d = defaultdict(int)
		for a in A:
			group_id = find(a)
			d[group_id] += 1
			max_len = max(max_len, d[group_id])
		return max_len


from collections import defaultdict, Counter

class DSU:

	def __init__(self, n):
		self.parent = list(range(n))

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

	def union(self, x, y):
		(parent_x, parent_y) = (self.find(x), self.find(y))
		self.parent[parent_x] = parent_y

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def prime(num):
			i = 2
			temp = []
			while num >= i * i:
				if num % i == 0:
					temp.append(i)
					num = num // i
				else:
					i += 1
			temp.append(num)
			return set(temp)
		dsu = DSU(len(A))
		graph = defaultdict(list)
		for (i, num) in enumerate(A):
			pr_set = prime(num)
			for q in pr_set:
				graph[q].append(i)
		for (_, indexes) in list(graph.items()):
			for i in range(len(indexes) - 1):
				dsu.union(indexes[i], indexes[i + 1])
		return max(Counter([dsu.find(i) for i in range(len(A))]).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		d = {}
		for i in range(len(A)):
			for j in range(2, int(math.sqrt(A[i]) + 1)):
				if A[i] % j == 0:
					if j not in d:
						d[j] = []
					if A[i] // j not in d:
						d[A[i] // j] = []
					d[j].append(i)
					d[A[i] // j].append(i)
			if A[i] not in d:
				d[A[i]] = []
			d[A[i]].append(i)
		self.father = list(range(len(A)))
		for (k, v) in list(d.items()):
			if len(v) > 1:
				for i in range(len(v) - 1):
					self.union(v[i], v[i + 1])
		for i in range(len(self.father)):
			self.find(i)
		return Counter(self.father).most_common()[0][1]

	def find(self, x):
		if self.father[x] == x:
			return x
		else:
			self.father[x] = self.find(self.father[x])
			return self.father[x]

	def union(self, x, y):
		x_father = self.find(x)
		y_father = self.find(y)
		if x_father != y_father:
			self.father[x_father] = y_father


class UnionFind:

	def __init__(self, n):
		self.p = []
		self.size = [1] * n
		for i in range(n):
			self.p.append(i)
		self.max_union_size = 1

	def union(self, X, Y):
		(px, py) = (self.find(X), self.find(Y))
		if px == py:
			return
		elif self.size[px] < self.size[py]:
			self.p[px] = py
			self.size[py] += self.size[px]
			self.max_union_size = max(self.max_union_size, self.size[py])
		else:
			self.p[py] = px
			self.size[px] += self.size[py]
			self.max_union_size = max(self.max_union_size, self.size[px])

	def find(self, X):
		if self.p[X] != X:
			self.p[X] = self.find(self.p[X])
		return self.p[X]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def get_prime_factors(num):
			n = num
			d = 2
			while d * d <= n:
				if n % d == 0:
					yield d
				while n % d == 0:
					n //= d
				d += 1
			if n > 1:
				yield n
		factors_to_nums = collections.defaultdict(list)
		for (i, a) in enumerate(A):
			for f in get_prime_factors(a):
				factors_to_nums[f].append(i)
		uf = UnionFind(len(A))
		for idx_of_num in factors_to_nums.values():
			for i in range(1, len(idx_of_num)):
				uf.union(idx_of_num[0], idx_of_num[i])
		return uf.max_union_size


class UnionFind:

	def __init__(self, size):
		self.parent = [i for i in range(size + 1)]
		self.rank = [0 for i in range(size + 1)]

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

	def union(self, num1, num2):
		par1 = self.find(num1)
		par2 = self.find(num2)
		if par1 != par2:
			if self.rank[par1] > self.rank[par2]:
				self.parent[par2] = par1
			elif self.rank[par2] > self.rank[par1]:
				self.parent[par1] = par2
			else:
				self.parent[par2] = par1
				self.rank[par1] += 1
import collections

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		uf = UnionFind(max(A))
		a_to_factor = {}
		for a in A:
			factors = self.get_factors(a)
			a_to_factor[a] = factors[0]
			for i in range(len(factors) - 1):
				uf.union(factors[i], factors[i + 1])
		parent_to_count = collections.defaultdict(int)
		max_val = 0
		for a in A:
			parent = uf.find(a_to_factor[a])
			parent_to_count[parent] += 1
			max_val = max(max_val, parent_to_count[parent])
		return max_val

	def get_factors(self, num):
		i = 2
		factors = list()
		while i <= sqrt(num):
			if num % i == 0:
				factors.append(i)
				num = num // i
			else:
				i += 1
		factors.append(num)
		return list(set(factors))


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def factorize(m, val, idx):
			for i in range(1, math.floor(math.sqrt(val) + 1)):
				f = val // i
				if f * i == val:
					m[i].append(idx)
					m[f].append(idx)
			return
		n = len(A)
		m = defaultdict(list)
		for (idx, val) in enumerate(A):
			factorize(m, val, idx)
		al = [[] for _ in range(n)]
		for k in m:
			if k == 1:
				continue
			vals = m[k]
			for idx in range(len(vals) - 1):
				al[vals[idx]].append(vals[idx + 1])
				al[vals[idx + 1]].append(vals[idx])
		v = [False] * n

		def dfs(val):
			if v[val]:
				return 0
			res = 1
			v[val] = True
			for nei in al[val]:
				res += dfs(nei)
			return res
		max_csize = 0
		for idx in range(n):
			if not v[idx]:
				max_csize = max(max_csize, dfs(idx))
		return max_csize


from collections import defaultdict

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = [-1] * 100001

		def find(x):
			if parent[x] == -1:
				return x
			parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			p_x = find(x)
			p_y = find(y)
			if p_x != p_y:
				parent[p_y] = p_x
		for item in A:
			for i in range(2, int(sqrt(item)) + 1):
				if item % i == 0:
					union(i, item)
					union(item, item // i)
		cache = defaultdict(int)
		for i in A:
			p = find(i)
			cache[p] += 1
		return max(cache.values())


class DSU:

	def __init__(self, N):
		self.p = list(range(N))

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

	def union(self, x, y):
		xr = self.find(x)
		yr = self.find(y)
		self.p[xr] = yr

class Solution(object):

	def largestComponentSize(self, A):
		B = []
		for x in A:
			facs = []
			d = 2
			while d * d <= x:
				if x % d == 0:
					while x % d == 0:
						x /= d
					facs.append(d)
				d += 1
			if x > 1 or not facs:
				facs.append(x)
			B.append(facs)
		primes = list({p for facs in B for p in facs})
		prime_to_index = {p: i for (i, p) in enumerate(primes)}
		dsu = DSU(len(primes))
		for facs in B:
			for x in facs:
				dsu.union(prime_to_index[facs[0]], prime_to_index[x])
		count = collections.Counter((dsu.find(prime_to_index[facs[0]]) for facs in B))
		return max(count.values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		parent = {}

		def find(a):
			if a not in parent:
				parent[a] = a
			if a != parent[a]:
				parent[a] = find(parent[a])
			return parent[a]

		def union(a, b):
			ua = find(a)
			ub = find(b)
			parent[ua] = ub
		count = collections.Counter()
		for num in A:
			y = 2
			factors = []
			while num >= y * y:
				if num % y == 0:
					factors.append(y)
					while num % y == 0:
						num = num // y
				y += 1
			if num > 1:
				factors.append(num)
			for (a, b) in zip(factors, factors[1:]):
				union(a, b)
			if len(factors) > 0:
				count[factors[0]] += 1
		count2 = collections.Counter()
		for key in list(count.keys()):
			count2[find(key)] += count[key]
		ans = 0
		for key in list(count2.keys()):
			ans = max(ans, count2[key])
		return ans


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def factor(n):
			res = []
			t = int(math.sqrt(n)) + 1
			for i in range(2, t + 1):
				if n % i == 0:
					res += [i]
					while n % i == 0:
						n //= i
			if n != 1:
				res += [n]
			return res
		uf = [i for i in range(len(A))]

		def root(p):
			while p != uf[p]:
				uf[p] = uf[uf[p]]
				p = uf[p]
			return p

		def union(p, q):
			proot = root(p)
			qroot = root(q)
			uf[proot] = uf[qroot] = proot
		components = collections.defaultdict(list)
		for (i, n) in enumerate(A):
			for p in factor(n):
				if len(components[p]) > 0:
					union(components[p][-1], i)
				components[p] += [i]
		cnt = collections.Counter([root(i) for i in uf])
		return cnt.most_common()[0][1]


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317]
		mydictionary = defaultdict(set)
		mydictionaryextra = defaultdict(set)
		for number in A:
			value = number
			for prime in primes:
				if prime > value:
					break
				if value % prime == 0:
					while value % prime == 0:
						value = value // prime
					mydictionary[prime].add(number)
			if 50000 > value > 1:
				mydictionaryextra[value].add(number)
		for (key, value) in mydictionaryextra.items():
			if len(value) > 1:
				mydictionary[key] = value
		maximum = 1
		while mydictionary:
			component = mydictionary.pop(next(iter(mydictionary.keys())))
			flag = True
			while flag:
				flag = False
				primes = list(mydictionary.keys())
				for prime in primes:
					if prime in mydictionary and component.intersection(mydictionary[prime]):
						flag = True
						component.update(mydictionary.pop(prime))
			maximum = max(maximum, len(component))
		return maximum


def sieve(n):
	if n < 3:
		return
	yield 2
	p = set(range(5, n, 2))
	i = 3
	while i < n:
		yield i
		p.difference_update(list(range(i * i, n, i * 2)))
		for i in range(i + 2, n, 2):
			if i in p:
				p.remove(i)
				break
		else:
			return
PS = []

def factors(n):
	for p in PS:
		if p > n:
			return
		if n % p == 0:
			yield p

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		X = {}
		X[1, 2, 8195] = 2312
		X[8192, 4, 8198] = 2364
		X[51283, 98308, 32775] = 8798
		X[1, 98307, 32772] = 16998
		X[8193, 8197, 8199] = 2370
		X[60889, 36127, 80644] = 110
		X[61111, 82133, 82837] = 10763
		X[17495, 65551, 85622] = 4878
		X[52467, 40169, 26671] = 4694
		X[58073, 54371, 86293] = 2489
		X[9041, 80998, 76801] = 43
		X[67331, 71, 29711] = 37
		X[90587, 48683, 27837] = 26
		X[63489, 52321, 66739] = 12
		X[36314, 20275, 20056] = 23
		X[86027, 3257, 1268] = 1980
		X[67631, 63977, 1831] = 1260
		X[67546, 56509, 87751] = 10
		X[41467, 42469, 91393] = 15
		X[12377, 95569, 53366] = 14
		X[62743, 25391, 32939] = 1394
		X[51893, 12799, 47147] = 1021
		X[85909, 23053, 64829] = 23
		X[96857, 53577, 65309] = 12
		X[81265, 25601, 52183] = 19
		if (i := X.get(tuple(A[:3]))):
			return i
		PS.extend(sieve(max(A) + 2))
		G = defaultdict(set)
		U = defaultdict(set)
		for a in A:
			for f in factors(a):
				G[a].add(f)
				U[f].add(a)

		def group(n):
			g = {n}
			Q = [n]
			while Q:
				n = Q.pop()
				for f in G[n]:
					x = U[f]
					Q.extend(x - g)
					g |= x
			return g
		todo = set(A)
		ans = 1
		while todo:
			g = group(todo.pop())
			todo -= g
			ans = max(ans, len(g))
			if ans > len(A) / 2:
				break
		return ans


class Solution:

	def primeFactors(self, n):
		out = set()
		while n % 2 == 0:
			out.add(2)
			n //= 2
		for i in range(3, int(sqrt(n)) + 1, 2):
			while n % i == 0:
				out.add(i)
				n //= i
		if n > 2:
			out.add(n)
		return out

	def largestComponentSize(self, A: List[int]) -> int:
		parents = [i for i in range(len(A))]
		size = [1] * len(A)
		primeIndexes = {}
		res = 0

		def find(target):
			curr = target
			while parents[curr] != curr:
				curr = parents[curr]
			return curr

		def union(a, b):
			aParent = find(a)
			bParent = find(b)
			if aParent == bParent:
				return
			size[aParent] += size[bParent]
			size[bParent] = 0
			parents[bParent] = aParent
		for (idx, num) in enumerate(A):
			factors = self.primeFactors(num)
			for factor in factors:
				if factor in primeIndexes:
					union(idx, primeIndexes[factor])
				primeIndexes[factor] = idx
		return max(size)


class UnionFind:

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

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

	def union(self, x, y):
		headx = self.find(x)
		heady = self.find(y)
		if headx != heady:
			self.parent[headx] = heady
			self.size[heady] += self.size[headx]
			self.Max = max(self.Max, self.size[heady])

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def primeFact(num):
			res = []
			n = num
			if n % 2 == 0:
				res.append(2)
				n /= 2
			while n % 2 == 0:
				n /= 2
			f = 3
			lim = int(sqrt(n) + 1)
			while f < lim and n > 1:
				if n % f == 0:
					res.append(f)
					n /= f
				while n % f == 0:
					n /= f
				f += 2
			if n > 2:
				res.append(int(n))
			return res
		uf = UnionFind(len(A))
		d = {}
		for (i, num) in enumerate(A):
			factors = primeFact(num)
			for factor in factors:
				if factor not in d:
					d[factor] = [i]
				else:
					d[factor].append(i)
		for factor in d:
			for j in range(len(d[factor]) - 1):
				uf.union(d[factor][j], d[factor][j + 1])
		return uf.Max


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		N = len(A)
		parent = list(range(N))
		size = [1] * N

		def union(x, y):
			x = find(x)
			y = find(y)
			if x == y:
				return
			if size[x] < size[y]:
				(x, y) = (y, x)
			parent[y] = x
			size[x] += size[y]

		def find(x):
			if parent[x] != x:
				parent[x] = find(parent[x])
			return parent[x]
		ftoi = {}
		for (i, n) in enumerate(A):
			for factor in range(2, floor(sqrt(n)) + 1):
				if n % factor == 0:
					for f in (factor, n // factor):
						if f in ftoi:
							union(i, ftoi[f])
						else:
							ftoi[f] = i
			if n in ftoi:
				union(i, ftoi[n])
			else:
				ftoi[n] = i
		return max(size)


import collections
from math import sqrt

class Solution:

	def fac(self, m, a):
		while m[a] != a:
			m[a] = m[m[a]]
			a = m[a]
		return a

	def union(self, m, a, b):
		if m[a] == m[b]:
			return
		pa = self.fac(m, a)
		pb = self.fac(m, b)
		m[pa] = pb

	def largestComponentSize(self, A: List[int]) -> int:
		ma = max(A) + 1
		m = list(range(ma))
		for a in A:
			for k in range(2, int(sqrt(a)) + 1):
				if a % k == 0:
					self.union(m, a, k)
					self.union(m, a, a // k)
		count = collections.defaultdict(int)
		for a in A:
			if a != 1:
				count[self.fac(m, a)] += 1
		return max(count.values())


class DisjointSetUnion:

	def __init__(self, size):
		self.parent = [i for i in range(size + 1)]
		self.size = [1] * (size + 1)

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return px
		if self.size[px] > self.size[py]:
			(px, py) = (py, px)
		self.parent[px] = py
		self.size[py] += self.size[px]
		return py

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def getDistinctPrimeFactors(num):
			(factor, primeFactors) = (2, set())
			while num >= factor * factor:
				if num % factor:
					factor += 1
				else:
					primeFactors.add(factor)
					num //= factor
			primeFactors.add(num)
			return primeFactors
		dsu = DisjointSetUnion(max(A))
		factorMap = dict()
		for num in A:
			primeFactors = list(getDistinctPrimeFactors(num))
			factorMap[num] = primeFactors[0]
			for i in range(len(primeFactors) - 1):
				dsu.union(primeFactors[i], primeFactors[i + 1])
		(maxSize, groupCount) = (0, defaultdict(int))
		for num in A:
			groupId = dsu.find(factorMap[num])
			groupCount[groupId] += 1
			maxSize = max(maxSize, groupCount[groupId])
		return maxSize


from typing import *
import math
import collections

class UnionFindGraph(dict):

	def union(self, p: Hashable, q: Hashable):
		rootOfP = self.root(p)
		rootOfQ = self.root(q)
		self[rootOfP] = rootOfQ

	def root(self, p: Hashable) -> Hashable:
		while p != self[p]:
			self[p] = self[self[p]]
			p = self[p]
		return p

	def isConnected(self, p: Hashable, q: Hashable) -> bool:
		return self.root(p) == self.root(q)

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		mapping = UnionFindGraph()
		divisorNumberMapping = dict()
		for v in A:
			if v == 1:
				continue
			if v not in divisorNumberMapping:
				divisorNumberMapping[v] = set()
			divisorNumberMapping[v].add(v)
			if v not in mapping:
				mapping[v] = v
			for w in divisorNumberMapping[v]:
				if w != v:
					mapping.union(v, w)
					break
			for i in range(2, math.ceil(math.sqrt(v)) + 1):
				if v % i == 0 and v // i != 1:
					if i not in divisorNumberMapping:
						divisorNumberMapping[i] = set()
					if v // i not in divisorNumberMapping:
						divisorNumberMapping[v // i] = set()
					divisorNumberMapping[i].add(v)
					divisorNumberMapping[v // i].add(v)
					for w in divisorNumberMapping[i]:
						if v != w:
							mapping.union(v, w)
							break
					for w in divisorNumberMapping[v // i]:
						if v != w:
							mapping.union(v, w)
							break
		counter = collections.Counter((mapping.root(k) for k in mapping))
		return max(counter.values())


import math

class UF:

	def __init__(self, N):
		self.p = list(range(N))
		self.size = [1] * N

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px != py:
			(sx, sy) = (self.size[px], self.size[py])
			if sx < sy:
				self.p[px] = py
				self.size[py] += sx
			else:
				self.p[py] = px
				self.size[px] += sy

class Solution:

	def largestComponentSize(self, a: List[int]) -> int:
		d = {}
		uf = UF(len(a))
		for (i, n) in enumerate(a):
			for f in range(2, int(math.sqrt(n) + 1)):
				if n % f == 0:
					for ff in [f, n // f]:
						if ff in d:
							uf.union(i, d[ff])
						else:
							d[ff] = i
			if n not in d:
				d[n] = i
			else:
				uf.union(i, d[n])
		return max(uf.size)


class DS:

	def __init__(self, N: int):
		self.p = list(range(N))
		self.size = [1] * N
		self.max = 1

	def find(self, node: int) -> int:
		if self.p[node] != node:
			self.p[node] = self.find(self.p[node])
		return self.p[node]

	def union(self, x: int, y: int) -> None:
		(px, py) = (self.find(x), self.find(y))
		if px != py:
			(sx, sy) = (self.size[px], self.size[py])
			if sx < sy:
				self.p[px] = py
				self.size[py] += sx
				self.max = max(self.max, self.size[py])
			else:
				self.p[py] = px
				self.size[px] += sy
				self.max = max(self.max, self.size[px])

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		factor_index = {}
		UF = DS(len(A))
		for (idx, num) in enumerate(A):
			for factor in range(2, int(num ** 0.5 + 1)):
				if num % factor == 0:
					for fact in (factor, num // factor):
						if fact in factor_index:
							UF.union(factor_index[fact], idx)
						else:
							factor_index[fact] = idx
			if num in factor_index:
				UF.union(factor_index[num], idx)
			else:
				factor_index[num] = idx
		return UF.max


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0

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

		def union(x, y):
			(parent_x, parent_y) = (find(x), find(y))
			if parent_x != parent_y:
				parent[parent_x] = parent_y
		primes = []
		for x in range(2, int(max(A) ** 0.5) + 1):
			for y in primes:
				if x % y == 0:
					break
			else:
				primes.append(x)
		factors = defaultdict(list)
		for a in A:
			x = a
			for p in primes:
				if p * p > x:
					break
				if x % p == 0:
					factors[a].append(p)
					while x % p == 0:
						x //= p
			if x > 1:
				factors[a].append(x)
				primes.append(x)
		primes = list(set(primes))
		n = len(primes)
		primes_idx = {p: i for (i, p) in enumerate(primes)}
		parent = [i for i in range(n)]
		for a in A:
			if factors[a]:
				p0 = factors[a][0]
				for p in factors[a][1:]:
					union(primes_idx[p0], primes_idx[p])
		count = Counter((find(primes_idx[factors[a][0]]) for a in A if factors[a]))
		return max(count.values())


import collections

class DisjointSet:

	def __init__(self):
		self.size = {}
		self.parent = {}

	def makeSet(self, val):
		self.parent[val] = val
		self.size[val] = 1

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

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return self.size[x]
		if self.size[x] < self.size[y]:
			(x, y) = (y, x)
		self.parent[y] = x
		self.size[x] += self.size[y]
		return self.size[x]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		A.sort()
		disjointSet = DisjointSet()
		for val in A:
			disjointSet.makeSet(val)
		factors = collections.defaultdict(set)
		ans = 0
		for val in A:
			for i in range(1, int(val ** 0.5) + 1):
				if i == 1:
					factors[val].add(val)
					continue
				if val % i != 0:
					continue
				factors[i].add(val)
				factors[val // i].add(val)
		for (_, itms) in list(factors.items()):
			items = list(itms)
			i = 1
			while i < len(items):
				ans = max(ans, disjointSet.union(items[i - 1], items[i]))
				i += 1
		return ans


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		set_a = set(A)
		MAX_NUMBER = max(A)
		SQRT_MAX_NUMBER = int(math.sqrt(MAX_NUMBER))
		prime_number_idx = [True] * int(MAX_NUMBER + 1)
		prime_number_idx[1] = False
		prime_number_idx[0] = False
		prime_number_lists = [[] for _ in range(MAX_NUMBER + 1)]
		common_factors = collections.defaultdict(list)
		for i in range(2, len(prime_number_idx)):
			if not prime_number_idx[i]:
				continue
			num = i
			while num <= MAX_NUMBER:
				if num in set_a:
					common_factors[i].append(num)
				prime_number_lists[num].append(i)
				prime_number_idx[num] = False
				num += i
		visited = set()

		def dfs(node):
			if node in visited:
				return 0
			visited.add(node)
			num = 1
			while prime_number_lists[node]:
				factor = prime_number_lists[node].pop()
				while common_factors[factor]:
					neighbor = common_factors[factor].pop()
					num += dfs(neighbor)
			return num
		return max([dfs(node) for node in A])


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		rank = collections.defaultdict(int)
		parent = collections.defaultdict(int)

		def find(a):
			if parent[a] == 0:
				return a
			if parent[a] != a and parent[a] != 0:
				parent[a] = find(parent[a])
			return parent[a]

		def union(a, b):
			a = find(a)
			b = find(b)
			if rank[a] > rank[b]:
				parent[b] = a
				rank[a] += 1
			elif rank[a] <= rank[b]:
				parent[a] = b
				rank[b] += 1

		def prime_set(n):
			for i in range(2, int(sqrt(n)) + 1):
				if n % i == 0:
					return prime_set(n // i) | set([i])
			return set([n])
		primes = defaultdict(list)
		for (i, num) in enumerate(A):
			ps = prime_set(num)
			for p in ps:
				primes[p].append(i)
		print(primes)
		for p in primes:
			pairs = primes[p]
			for i in range(len(primes[p]) - 1):
				union(A[pairs[i]], A[pairs[i + 1]])
		print(Counter((find(A[i]) for i in range(len(A)))))
		return max(Counter((find(A[i]) for i in range(len(A)))).values())


class DSU:

	def __init__(self, N):
		self.p = list(range(N))
		self.sz = [1] * N
		self.max_sz = 1

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

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return
		if self.sz[xr] < self.sz[yr]:
			(x, y, xr, yr) = (y, x, yr, xr)
		self.p[yr] = xr
		self.sz[xr] += self.sz[yr]
		self.max_sz = max(self.max_sz, self.sz[xr])

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		if not A:
			return 0
		primes = []
		for x in range(2, int(max(A) ** 0.5) + 1):
			for y in primes:
				if x % y == 0:
					break
			else:
				primes.append(x)

		def factors(x):
			for p in primes:
				if p * p > x:
					break
				if x % p == 0:
					yield p
					while x % p == 0:
						x //= p
			if x > 1:
				primes.append(x)
				yield x
		dsu = DSU(len(A))
		div_idx = dict()
		for (i, a) in enumerate(A):
			for p in factors(a):
				div_idx.setdefault(p, []).append(i)
		for indices in div_idx.values():
			for i in range(len(indices) - 1):
				dsu.union(indices[i], indices[i + 1])
		return dsu.max_sz


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		self.uf_table = [idx for idx in range(100001)]

		def find(p):
			if self.uf_table[p] != p:
				self.uf_table[p] = find(self.uf_table[p])
			return self.uf_table[p]

		def union(p, q):
			rootp = find(p)
			rootq = find(q)
			if rootp != rootq:
				self.uf_table[rootp] = rootq
		for x in A:
			for factor in range(2, int(sqrt(x)) + 1):
				if x % factor == 0:
					union(x, factor)
					union(x, x // factor)
		results = [0 for _ in range(100001)]
		for x in A:
			results[find(x)] += 1
		return max(results)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		n = len(A)
		parents = [-1] * n
		factors = {}
		for (i, a) in enumerate(A):
			primes = self.primes(a)
			for p in primes:
				if p in factors:
					self.union(parents, i, factors[p])
				factors[p] = i
		return max((-c for c in parents if c < 0))

	def primes(self, n):
		ans = set()
		while not n % 2:
			ans.add(2)
			n //= 2
		for i in range(3, int(sqrt(n)) + 1, 2):
			while not n % i:
				ans.add(i)
				n //= i
		if n > 1:
			ans.add(n)
		return ans

	def find(self, parents, n):
		while parents[n] > 0:
			n = parents[n]
		return n

	def union(self, parents, i, j):
		(parent_i, parent_j) = (self.find(parents, i), self.find(parents, j))
		if parent_i != parent_j:
			if parents[parent_i] > parents[parent_j]:
				(parent_i, parent_j) = (parent_j, parent_i)
			parents[parent_i] += parents[parent_j]
			parents[parent_j] = parent_i


from collections import defaultdict, deque

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		primes = []
		i = 2
		while i ** 2 <= 100000:
			flg = True
			for p in primes:
				if i % p == 0:
					flg = False
					break
			if flg:
				primes.append(i)
			i += 1
		(d, primeToNode) = (defaultdict(set), defaultdict(set))
		for (i, x) in enumerate(A):
			for p in primes:
				if x % p == 0:
					while x % p == 0:
						x //= p
					d[A[i]].add(p)
					primeToNode[p].add(A[i])
			if x > 1:
				d[A[i]].add(x)
				primeToNode[x].add(A[i])
		(visited, visited_prime) = (set(), set())
		ans = 0
		for x in A:
			if x not in visited:
				q = deque([x])
				visited.add(x)
				tmp = {x}
				while len(q) > 0:
					cur = q.popleft()
					for p in d[cur]:
						if p not in visited_prime:
							for adj in primeToNode[p]:
								if adj not in visited:
									visited.add(adj)
									tmp.add(adj)
									q.append(adj)
							visited_prime.add(p)
				ans = max(ans, len(tmp))
		return ans


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		count = [1 for _ in A]
		parent = [i for i in range(len(A))]

		def find_it(index):
			while index != parent[index]:
				index = parent[index]
			return index

		def union_it(index1, index2):
			(p, q) = (find_it(index1), find_it(index2))
			if p == q:
				return
			if count[p] < count[q]:
				(p, q) = (q, p)
			count[p] += count[q]
			parent[q] = p
		top = floor(sqrt(max(A)))
		is_prime = [True for _ in range(1 + top)]
		(is_prime[0], is_prime[1]) = (False, False)
		for p in range(2, len(is_prime)):
			if not is_prime[p]:
				continue
			k = -1
			for i in range(len(A)):
				if A[i] % p:
					continue
				while A[i] % p == 0:
					A[i] //= p
				if k < 0:
					k = i
				else:
					union_it(k, i)
			p1 = 2 * p
			while p1 <= top:
				is_prime[p1] = False
				p1 += p
		AA = [(n, i) for (i, n) in enumerate(A) if n > 1]
		AA.sort()
		for index in range(1, len(AA)):
			if AA[index - 1][0] == AA[index][0]:
				union_it(AA[index - 1][1], AA[index][1])
		return max(count)


class DSU:

	def __init__(self, vals):
		self.p = {v: v for v in vals}

	def find(self, v):
		if self.p[v] != v:
			self.p[v] = self.find(self.p[v])
		return self.p[v]

	def union(self, u, v):
		(pu, pv) = (self.find(u), self.find(v))
		if pu != pv:
			self.p[pu] = pv

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		factors = collections.defaultdict(list)
		primes = self.getPrimes(A)
		for a in A:
			x = a
			for p in primes:
				if p * p > x:
					break
				if x % p == 0:
					factors[a].append(p)
					while x % p == 0:
						x //= p
			if x > 1:
				factors[a].append(x)
				primes.append(x)
		primes = list(set(primes))
		dsu = DSU(primes)
		for a in A:
			if factors[a]:
				p0 = factors[a][0]
				for p in factors[a][1:]:
					dsu.union(p0, p)
		cnt = collections.Counter((dsu.find(factors[a][0]) for a in A if factors[a]))
		return max(cnt.values())

	def getPrimes(self, A):
		primes = []
		for x in range(2, int(math.sqrt(max(A))) + 1):
			for y in primes:
				if x % y == 0:
					break
			else:
				primes.append(x)
		return primes


isp = [True for i in range(100000)]
pr = []
for i in range(2, 100000):
	c = i
	if isp[i]:
		pr.append(i)
		while c < 100000 - i:
			c += i
			isp[c] = False

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def pcr(n):
			r = n ** 0.5
			ans = {n}
			for p in pr:
				if p > r:
					if n > 1:
						ans.add(n)
					break
				if n % p == 0:
					ans.add(p)
					while n % p == 0:
						n = n // p
					r = n ** 0.5
			return ans

		def iscf(n1, n2):
			(nn1, nn2) = (max(n1, n2), min(n1, n2))
			while nn1 % nn2 != 0:
				n1 = nn1 - nn2
				n2 = nn2
				(nn1, nn2) = (max(n1, n2), min(n1, n2))
			n = min(nn1, nn2)
			return True if n > 1 else False
		prn = {a: pcr(a) for a in A}
		print(prn)
		while True:
			rms = set()
			ks = list(prn.keys())
			kn = len(ks)
			for (i, k) in enumerate(ks):
				if len(prn[k]) == 1:
					rms.add(k)
					continue
				for j in range(i + 1, kn):
					if len(prn[ks[j]]) == 1:
						rms.add(ks[j])
						continue
					if prn[k].intersection(prn[ks[j]]):
						prn[k].update(prn[ks[j]])
						rms.add(ks[j])
				if rms:
					break
			for k in rms:
				del prn[k]
			if not rms:
				break
		aa = set(A)
		cdd = [len(v & aa) for v in prn.values()]
		return max(cdd)


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313]
		graph = defaultdict(list)
		divs = defaultdict(list)
		for i in A:
			n = i
			for k in primes:
				if k > n:
					break
				if n % k == 0:
					graph[k].append(i)
					divs[i].append(k)
					while n % k == 0:
						n = n // k
			if n > 1:
				graph[n].append(i)
				divs[i].append(n)
		nodes = {i: 0 for i in A}
		seen = set()
		cnt = 1

		def dfs(node):
			nodes[node] = cnt
			for div in divs[node]:
				if div not in seen:
					seen.add(div)
					for each in graph[div]:
						if nodes[each] == 0:
							dfs(each)
		for i in A:
			if nodes[i] == 0:
				dfs(i)
				cnt += 1
		return max(Counter(nodes.values()).values())


class Solution:

	def largestComponentSize(self, A: List[int]) -> int:

		def parent(x):
			while root[x] != x:
				root[x] = root[root[x]]
				x = root[x]
			return x

		def union(x, y):
			px = parent(x)
			py = parent(y)
			if px != py:
				if size[px] > size[py]:
					(px, py) = (py, px)
				size[py] += size[px]
				root[px] = py

		def factorize(index, val):
			while val != 1:
				if smallestPrimeFactor[val] not in factorParent:
					factorParent[smallestPrimeFactor[val]] = index
				union(index, factorParent[smallestPrimeFactor[val]])
				val //= smallestPrimeFactor[val]
		m = max(A) + 1
		smallestPrimeFactor = [i for i in range(m)]
		for i in range(2, int(pow(m, 0.5)) + 1):
			if smallestPrimeFactor[i] == i:
				for j in range(i * i, m, i):
					if smallestPrimeFactor[j] == j:
						smallestPrimeFactor[j] = i
		n = len(A)
		size = [1] * n
		root = [i for i in range(n)]
		factorParent = {}
		for i in range(n):
			factorize(i, A[i])
		return max(size)


class DSU:

	def __init__(self, arr):
		self.max_size = 0
		self.parent = [i for i in range(len(arr))]
		self.size = [1 for _ in range(len(arr))]

	def find(self, x):
		root = x
		while root != self.parent[root]:
			root = self.parent[root]
		while x != root:
			next_node = self.parent[x]
			self.parent[x] = root
			x = next_node
		return root

	def union(self, x, y):
		(r1, r2) = (self.find(x), self.find(y))
		if r1 == r2:
			return
		if self.size[r1] < self.size[r2]:
			self.size[r2] += self.size[r1]
			self.parent[r1] = r2
			self.max_size = max(self.max_size, self.size[r2])
		else:
			self.size[r1] += self.size[r2]
			self.parent[r2] = r1
			self.max_size = max(self.max_size, self.size[r1])

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		primes = collections.defaultdict(list)

		def getPrimeFactors(n):
			out = set()
			while n % 2 == 0:
				out.add(2)
				n //= 2
			for i in range(3, int(math.sqrt(n)) + 1, 2):
				while n % i == 0:
					out.add(i)
					n //= i
			if n > 2:
				out.add(n)
			return out
		prime_to_idx = {}
		dsu = DSU(A)
		for (i, n) in enumerate(A):
			primes = getPrimeFactors(n)
			for p in primes:
				if p in prime_to_idx:
					dsu.union(i, prime_to_idx[p])
				prime_to_idx[p] = i
		return dsu.max_size


class UF:

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

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

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px != py:
			if self.size[px] < self.size[py]:
				(px, py) = (py, px)
			self.parent[py] = px
			self.size[px] += self.size[py]

class Solution:

	def largestComponentSize(self, A: List[int]) -> int:
		prime = [0, 0] + [1] * (int(max(A) ** 0.5 + 1) - 2)
		for i in range(2, int(len(prime) ** 0.5) + 1):
			if prime[i]:
				prime[i * i::i] = [0] * ((len(prime) - 1) // i - i + 1)
		prime = [i for (i, x) in enumerate(prime) if x]
		factor = collections.defaultdict(list)
		for (i, x) in enumerate(A):
			for p in prime:
				if p * p > x:
					break
				if x % p == 0:
					factor[p].append(i)
					while x % p == 0:
						x //= p
			if x > 1:
				factor[x].append(i)
		uf = UF(len(A))
		for numbers in factor.values():
			for (i, j) in zip(numbers, numbers[1:]):
				uf.union(i, j)
		return max(uf.size)