You are given two positive integers $$$a$$$ and $$$b$$$. There are two possible operations:   multiply one of the numbers by some prime $$$p$$$;  divide one of the numbers on its prime factor $$$p$$$. What is the minimum number of operations required to obtain two integers having the same number of divisors? You are given several such pairs, you need to find the answer for each of them.

The first line contains a single integer $$$t$$$ ($$$1 \le t \le 10^5$$$) — the number of pairs of integers for which you are to find the answer. Each of the next $$$t$$$ lines contain two integers $$$a_i$$$ and $$$b_i$$$ ($$$1 \le a_i, b_i \le 10^6$$$).

Output $$$t$$$ lines — the $$$i$$$-th of them should contain the answer for the pair $$$a_i$$$, $$$b_i$$$.

NoteThese are the numbers with equal number of divisors, which are optimal to obtain in the sample test case:   $$$(27, 10)$$$, 4 divisors  $$$(100, 1156)$$$, 9 divisors  $$$(220, 140)$$$, 12 divisors  $$$(17, 19)$$$, 2 divisors  $$$(12, 18)$$$, 6 divisors  $$$(50, 32)$$$, 6 divisors  $$$(224, 1925)$$$, 12 divisors Note that there can be several optimal pairs of numbers.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.TreeMap;

public class Techno19_2F {

	static int MODE = -1;

	static final Comparator<int[]> COMP_ARR = new Comparator<int[]>() {
		public int compare(int[] a1, int[] a2) {
			if (MODE != -1 && (a1.length == 32 || a2.length == 32)) {
				if (a1.length == 32) {
					if (MODE < a2.length) {
						return -1;
					}
					if (MODE > a2.length) {
						return 1;
					}
				} else {
					if (a1.length < MODE) {
						return -1;
					}
					if (a1.length > MODE) {
						return 1;
					}
				}

				for (int i = 0; i < MODE; i++) {
					if (a1[i] < a2[i]) {
						return -1;
					}
					if (a1[i] > a2[i]) {
						return 1;
					}
				}
				return 0;
			} else {
				if (a1.length < a2.length) {
					return -1;
				}
				if (a1.length > a2.length) {
					return 1;
				}

				for (int i = 0; i < a2.length; i++) {
					if (a1[i] < a2[i]) {
						return -1;
					}
					if (a1[i] > a2[i]) {
						return 1;
					}
				}
				return 0;
			}
		}
	};

	static TreeMap<int[], Integer> index = new TreeMap<>(COMP_ARR);
	static int[][] states;

	static ArrayList<int[]> start = new ArrayList<>();

	static int[] numD;

	static int[] pFact = new int[1_000_001];

	static TreeMap<int[], Integer> divCostInd = new TreeMap<>(COMP_ARR);

	public static void main(String[] args) throws IOException {
		cGen = new int[23];
		numD = new int[6000];
		states = new int[6000][];
		genAll(0, 23, 23, 1);

		aList = new ArrayList[6000];
		for (int i = 0; i < 6000; i++) {
			aList[i] = new ArrayList<>();
		}
		fAList();

		divCost = new int[400][301];
		for (int[] a : divCost) {
			Arrays.fill(a, Integer.MAX_VALUE / 2);
		}
		cost = new int[index.size()];

		Arrays.fill(pFact, 1);
		for (int i = 2; i <= 1_000_000; i++) {
			if (pFact[i] == 1) {
				for (int m = i; m <= 1_000_000; m += i) {
					pFact[m] = i;
				}
			}
		}

		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter printer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

		int nT = Integer.parseInt(reader.readLine());

		while (nT-- > 0) {
			StringTokenizer inputData = new StringTokenizer(reader.readLine());
			int a = Integer.parseInt(inputData.nextToken());
			int b = Integer.parseInt(inputData.nextToken());

			int[] aA = toArray(a);
			int[] bA = toArray(b);

			Integer aRes = divCostInd.get(aA);
			if (aRes == null) {
				aRes = divCostInd.size();
				bfs(aA, divCostInd.size());
				divCostInd.put(aA, divCostInd.size());
			}
			Integer bRes = divCostInd.get(bA);
			if (bRes == null) {
				bRes = divCostInd.size();
				bfs(bA, divCostInd.size());
				divCostInd.put(bA, divCostInd.size());
			}

			int minA = Integer.MAX_VALUE / 4;
			for (int nD = 1; nD <= 300; nD++) {
				minA = Math.min(minA, divCost[aRes][nD] + divCost[bRes][nD]);
			}
			printer.println(minA);
		}
		printer.close();
	}

	static int[] toArray(int a) {
		ArrayList<Integer> cnts = new ArrayList<Integer>();
		int last = -1;
		int cCnt = 0;

		while (a > 1) {
			int cPFact = pFact[a];
			if (cPFact == last) {
				cCnt++;
			} else {
				if (cCnt != 0) {
					cnts.add(cCnt);
				}
				last = cPFact;
				cCnt = 1;
			}
			a /= pFact[a];
		}
		if (cCnt != 0) {
			cnts.add(cCnt);
		}
		Collections.sort(cnts, Comparator.reverseOrder());
		int[] res = new int[cnts.size()];
		for (int i = 0; i < cnts.size(); i++) {
			res[i] = cnts.get(i);
		}
		return res;
	}

	static int[] cost;

	static int[][] divCost;

	static void bfs(int[] sState, int searchI) {
		int sInd = index.get(sState);
		ArrayDeque<Integer> queue = new ArrayDeque<>();

		queue.add(index.get(sState));

		Arrays.fill(cost, -1);
		cost[sInd] = 0;

		while (!queue.isEmpty()) {
			int cStInd = queue.remove();
			for (int nStInd : aList[cStInd]) {
				if (cost[nStInd] == -1) {
					cost[nStInd] = cost[cStInd] + 1;
					queue.add(nStInd);
				}
			}
		}

		for (Entry<int[], Integer> cE : index.entrySet()) {
			int cNumD = numD[cE.getValue()];
			if (cNumD <= 300) {
				divCost[searchI][cNumD] = Math.min(divCost[searchI][cNumD], cost[cE.getValue()]);
			}
		}
	}

	static ArrayList<Integer>[] aList;

	static void fAList() {
		int[] cState = new int[32];
		for (Entry<int[], Integer> cE : index.entrySet()) {
			int[] oState = cE.getKey();
			int cStInd = cE.getValue();

			int cLen = states[cStInd].length;
			for (int i = 0; i < cLen; i++) {
				cState[i] = oState[i];
			}
			MODE = cLen;

			for (int i = 0; i < cLen; i++) {
				if (i == 0 || cState[i - 1] > cState[i]) {
					cState[i]++;
					Integer nStInd = index.get(cState);
					cState[i]--;

					if (nStInd == null) {
						continue;
					}
					aList[cStInd].add(nStInd);
				}

				if (i == cLen - 1 && cState[i] == 1) {
					MODE--;
					Integer nStInd = index.get(cState);
					MODE++;
					if (nStInd == null) {
						continue;
					}
					aList[cStInd].add(nStInd);
				} else if (i == cLen - 1 || cState[i] > cState[i + 1]) {
					cState[i]--;
					Integer nStInd = index.get(cState);
					cState[i]++;
					if (nStInd == null) {
						continue;
					}
					aList[cStInd].add(nStInd);
				}
			}
			cState[cLen] = 1;

			MODE++;
			Integer nStInd = index.get(cState);
			MODE--;
			if (nStInd == null) {
				continue;
			}
			aList[cStInd].add(nStInd);
		}
	}

	static int[] cGen;

	static void genAll(int i, int max, int rem, int cProd) {
		numD[index.size()] = cProd;

		int[] cKey = Arrays.copyOf(cGen, i);
		states[index.size()] = cKey;
		index.put(cKey, index.size());

		if (rem > 0) {
			for (int nV = Math.min(max, rem); nV >= 1; nV--) {
				cGen[i] = nV;
				genAll(i + 1, nV, rem - nV, cProd * (nV + 1));
			}
		}
	}
}

//package round517;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.InputMismatchException;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class D3 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int[] lpf = enumLowestPrimeFactors(1000000);
		Map<Long, int[]> map = new HashMap<>();
		long[] hs = new long[1000001];
		for(int i = 1;i <= 1000000;i++){
			int[] lu = factorE(i, lpf);
			Arrays.sort(lu);
			hs[i] = (long)Arrays.hashCode(lu);
			map.put(hs[i], lu);
		}

		int K = 8;
		List<List<Set<Long>>> ls = new ArrayList<>();
		List<int[]> vs = new ArrayList<>(map.values());
		int gen = 0;
		Map<Long, Integer> htov = new HashMap<>();
		for(int[] v : vs){
			htov.put((long)Arrays.hashCode(v), gen++);
			cache = new HashSet<>();
			List<Set<Long>> hey = new ArrayList<>();
			for(int t = 0;t <= K;t++)hey.add(new HashSet<>());
			dfs(v, 0, K, hey);
			ls.add(hey);
		}

		int[][] cans = new int[ls.size()][ls.size()];
		for(int i = 0;i < ls.size();i++){
			Arrays.fill(cans[i], -1);
		}

		outer:
		for(int T = ni();T > 0;T--){
			int a = ni(), b = ni();
			int ia = htov.get(hs[a]);
			int ib = htov.get(hs[b]);
			if(cans[ia][ib] != -1){
				out.println(cans[ia][ib]);
				continue;
			}
			for(int d = 0;d <= 16;d++){
				for(int i = 0;i <= d && i <= 8;i++){
					int j = d-i;
					if(j >= 0 && j <= 8){
						if(!Collections.disjoint(ls.get(ia).get(i), ls.get(ib).get(j))){
							cans[ia][ib] = cans[ib][ia] = d;
							out.println(d);
							continue outer;
						}
					}
				}
			}
			throw new RuntimeException();
		}
	}

	Set<Long> cache = new HashSet<>();

	void dfs(int[] a, int dep, int lim, List<Set<Long>> set)
	{
		long h = dep + 114514;
		for(int v : a)h = h * 1000000009 + v;
		if(!cache.add(h)){
			return;
		}

		long x = 1;
		for(int v : a){
			x = x * (v+1);
		}
		set.get(dep).add(x);
		if(dep == lim)return;

		for(int i = 0;i < a.length;i++){
			if(i > 0 && a[i] == a[i-1])continue;
			if(a[i] > 1){
				int[] b = Arrays.copyOf(a, a.length);
				b[i]--;
				Arrays.sort(b);
				dfs(b, dep+1, lim, set);
			}
			{
				int[] b = Arrays.copyOf(a, a.length);
				b[i]++;
				Arrays.sort(b);
				dfs(b, dep+1, lim, set);
			}
			if(a[i] == 1){
				int[] b = Arrays.copyOf(a, a.length-1);
				int p = 0;
				for(int j = 0;j < a.length;j++){
					if(j == i)continue;
					b[p++] = a[j];
				}
				dfs(b, dep+1, lim, set);
			}
		}
		int[] b = Arrays.copyOf(a, a.length+1);
		b[a.length] = 1;
		Arrays.sort(b);
		dfs(b, dep+1, lim, set);
	}

	public static int[] factorE(int n, int[] lpf)
	{
		int[] f = new int[9];
		int q = 0;
		int pre = -1;
		while(lpf[n] > 0){
			int p = lpf[n];
			if(p != pre){
				pre = p;
				f[q++] = 1;
			}else{
				f[q-1]++;
			}
			n /= p;
		}
		if(n > 1){
			// big prime
			return new int[]{1};
		}
		return Arrays.copyOf(f, q);
	}

	public static int[] enumLowestPrimeFactors(int n) {
		int tot = 0;
		int[] lpf = new int[n + 1];
		int u = n + 32;
		double lu = Math.log(u);
		int[] primes = new int[(int) (u / lu + u / lu / lu * 1.5)];
		for (int i = 2; i <= n; i++)
			lpf[i] = i;
		for (int p = 2; p <= n; p++) {
			if (lpf[p] == p)
				primes[tot++] = p;
			int tmp;
			for (int i = 0; i < tot && primes[i] <= lpf[p] && (tmp = primes[i] * p) <= n; i++) {
				lpf[tmp] = primes[i];
			}
		}
		return lpf;
	}

	void run() throws Exception
	{
//		int n = 99999, m = 99999;
//		StringBuilder sb = new StringBuilder();
//		sb.append(n + " ");
//		for (int i = 0; i < n; i++) {
//			sb.append(36 + " " + (3*5*7*11<<9) + "\n");
//		}
//		INPUT = sb.toString();

		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new D3().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}