Problem: You are given two positive integers a and b. There are two possible operations: 

  1. multiply one of the numbers by some prime p; 
  2. 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.

Input

The first line contains a single integer t (1 ≤ t ≤ 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 ≤ a_i, b_i ≤ 10^6).

Output

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

Example

Input

8
9 10
100 17
220 70
17 19
4 18
32 20
100 32
224 385


Output

1
3
1
0
1
0
1
1

Note

These 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.

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
namespace {
const vector<int> primes = {2, 3, 5, 7, 11, 13, 17, 19, 23};
constexpr int NUM_P = 7;
const int MAX = 1000002;
const int MAX_V = 1024;
const int MAX_DIVS = 300;
int dist[MAX_V][MAX_V];
int cost[MAX_V][MAX_DIVS];
vector<int> adj[MAX_V];
void Chmin(int& a, int b) { a = min(a, b); }
void Solve(int) {
  const greater<int> cmp;
  vector<array<int, NUM_P> > verts;
  vector<array<int, NUM_P> > facts(MAX);
  {
    vector<int> idx(MAX);
    for (int p = 2, __p = MAX; p < __p; ++p)
      if (idx[p] == 0) {
        for (int j = p; j < MAX; j += p) {
          int temp = j, ex = 0;
          while (temp % p == 0) {
            ++ex;
            temp /= p;
          }
          facts[j][idx[j]++] = ex;
        }
      }
  }
  for (int i = 1, __i = MAX; i < __i; ++i) {
    sort(facts[i].begin(), facts[i].end(), cmp);
  }
  {
    const int64_t lim = int64_t(1) << 50;
    function<void(int64_t, int, int, int, array<int, NUM_P>&)> gen =
        [&](int64_t prod, int num_divs, int prev_ex, int p,
            array<int, NUM_P>& row) {
          if (num_divs >= MAX_DIVS) return;
          if (p == NUM_P) {
            verts.push_back(row);
            return;
          }
          int64_t new_prod = prod;
          for (int ex = 0, __ex = prev_ex + 1; ex < __ex; ++ex) {
            row[p] = ex;
            if (new_prod < lim)
              gen(new_prod, num_divs * (ex + 1), ex, p + 1, row);
            else
              break;
            new_prod *= primes[p];
          }
        };
    array<int, NUM_P> row;
    gen(1, 1, 100, 0, row);
  }
  sort(verts.begin(), verts.end());
  verts.erase(unique(verts.begin(), verts.end()), verts.end());
  const int num_verts = ((int)(verts.size()));
  assert(num_verts < MAX_V);
  vector<int> num_divs(num_verts, 1);
  for (int v = 0, __v = num_verts; v < __v; ++v)
    for (int i = 0, __i = NUM_P; i < __i; ++i) num_divs[v] *= verts[v][i] + 1;
  assert(*max_element(num_divs.begin(), num_divs.end()) < MAX_DIVS);
  auto get_idx = [&](const array<int, NUM_P>& row) {
    const int idx =
        lower_bound(verts.begin(), verts.end(), row) - verts.begin();
    if (idx >= num_verts or verts[idx] != row)
      return -1;
    else
      return idx;
  };
  {
    for (int st = 0, __st = num_verts; st < __st; ++st) {
      const auto& row = verts[st];
      for (int j = 0, __j = NUM_P; j < __j; ++j) {
        for (int diff = -1; diff <= 1; diff += 2) {
          auto to_row = row;
          to_row[j] += diff;
          sort(to_row.begin(), to_row.end(), cmp);
          auto to_idx = get_idx(to_row);
          if (~to_idx) {
            adj[st].push_back(to_idx);
          }
        }
      }
    }
  }
  {
    memset(dist, -1, sizeof(dist));
    memset(cost, 0x3F, sizeof(cost));
    queue<int> que;
    for (int st = 0, __st = num_verts; st < __st; ++st) {
      que.push(st);
      dist[st][st] = 0;
      while (not que.empty()) {
        const int at = que.front();
        for (auto& to : adj[at])
          if (dist[st][to] == -1) {
            dist[st][to] = dist[st][at] + 1;
            que.push(to);
          }
        que.pop();
      }
      for (int to = 0, __to = num_verts; to < __to; ++to)
        Chmin(cost[st][num_divs[to]], dist[st][to]);
    }
  }
  int q;
  cin >> q;
  for (int _ = 0, ___ = q; _ < ___; ++_) {
    int a, b;
    cin >> a >> b;
    const int x = get_idx(facts[a]), y = get_idx(facts[b]);
    assert(~x and ~y);
    int res = 100000;
    for (int divs = 1, __divs = MAX_DIVS; divs < __divs; ++divs) {
      Chmin(res, cost[x][divs] + cost[y][divs]);
    }
    cout << res << '\n';
  }
}
void Init() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
}
}  // namespace
int32_t main() {
  Init();
  int tests = 1;
  for (int test = 1, __test = tests + 1; test < __test; ++test) Solve(test);
  return 0;
}