description: Consider a sequence of distinct integers a_1, …, a_n, each representing one node of a graph. There is an edge between two nodes if the two values are not coprime, i. e. they have a common divisor greater than 1.
  
  There are q queries, in each query, you want to get from one given node a_s to another a_t. In order to achieve that, you can choose an existing value a_i and create new value a_{n+1} = a_i ⋅ (1 + a_i), with edges to all values that are not coprime with a_{n+1}. Also, n gets increased by 1. You can repeat that operation multiple times, possibly making the sequence much longer and getting huge or repeated values. What's the minimum possible number of newly created nodes so that a_t is reachable from a_s?
  
  Queries are independent. In each query, you start with the initial sequence a given in the input.
  
  Input
  
  The first line contains two integers n and q (2 ≤ n ≤ 150 000, 1 ≤ q ≤ 300 000) — the size of the sequence and the number of queries.
  
  The second line contains n distinct integers a_1, a_2, …, a_n (2 ≤ a_i ≤ 10^6, a_i ≠ a_j if i ≠ j).
  
  The j-th of the following q lines contains two distinct integers s_j and t_j (1 ≤ s_j, t_j ≤ n, s_j ≠ t_j) — indices of nodes for j-th query.
  
  Output
  
  Print q lines. The j-th line should contain one integer: the minimum number of new nodes you create in order to move from a_{s_j} to a_{t_j}.
  
  Examples
  
  Input
  
  
  3 3
  2 10 3
  1 2
  1 3
  2 3
  
  
  Output
  
  
  0
  1
  1
  
  
  Input
  
  
  5 12
  3 8 7 6 25
  1 2
  1 3
  1 4
  1 5
  2 1
  2 3
  2 4
  2 5
  3 1
  3 2
  3 4
  3 5
  
  
  Output
  
  
  0
  1
  0
  1
  0
  1
  0
  1
  1
  1
  1
  2
  
  Note
  
  In the first example, you can first create new value 2 ⋅ 3 = 6 or 10 ⋅ 11 = 110 or 3 ⋅ 4 = 12. None of that is needed in the first query because you can already get from a_1 = 2 to a_2 = 10.
  
  In the second query, it's optimal to first create 6 or 12. For example, creating 6 makes it possible to get from a_1 = 2 to a_3 = 3 with a path (2, 6, 3).
  
  <image>
  
  In the last query of the second example, we want to get from a_3 = 7 to a_5 = 25. One way to achieve that is to first create 6 ⋅ 7 = 42 and then create 25 ⋅ 26 = 650. The final graph has seven nodes and it contains a path from a_3 = 7 to a_5 = 25.
solution: import java.io.OutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.Arrays;
  import java.util.Random;
  import java.util.HashSet;
  import java.io.OutputStream;
  import java.util.Set;
  import java.io.IOException;
  import java.lang.reflect.Field;
  import java.nio.charset.StandardCharsets;
  import java.io.UncheckedIOException;
  import java.io.Closeable;
  import java.io.InputStream;
  
  /**
   * Built using CHelper plug-in
   * Actual solution is at the top
   */
  public class Main {
      public static void main(String[] args) throws Exception {
          Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 29);
          thread.start();
          thread.join();
      }
  
      static class TaskAdapter implements Runnable {
          @Override
          public void run() {
              InputStream inputStream = System.in;
              OutputStream outputStream = System.out;
              FastInput in = new FastInput(inputStream);
              FastOutput out = new FastOutput(outputStream);
              GCommonDivisorGraph solver = new GCommonDivisorGraph();
              solver.solve(1, in, out);
              out.close();
          }
      }
  
      static class GCommonDivisorGraph {
          public long id(int a, int b) {
              if (a < b) {
                  return DigitUtils.asLong(a, b);
              } else {
                  return DigitUtils.asLong(b, a);
              }
          }
  
          public void solve(int testNumber, FastInput in, FastOutput out) {
              int n = in.ri();
              int q = in.ri();
              int[] a = in.ri(n);
              int L = (int) 1e6;
              IntegerMultiWayStack primes = Factorization.factorizeRangePrime((int) 1e6 + 10);
              DSU dsu = new DSU(n);
              dsu.init();
              Set<Integer>[] sets = new Set[n];
              for (int i = 0; i < n; i++) {
                  sets[i] = new HashSet<>();
              }
  
              LongHashSet em = new LongHashSet(7 * 6 / 2 * n, false);
              IntegerArrayList list = new IntegerArrayList(10);
              int[] reg = new int[L + 10];
              Arrays.fill(reg, -1);
              for (int i = 0; i < n; i++) {
                  int x = a[i];
  
                  for (IntegerIterator iterator = primes.iterator(x); iterator.hasNext(); ) {
                      int p = iterator.next();
                      if (reg[p] == -1) {
                          reg[p] = i;
                      }
                      dsu.merge(reg[p], i);
                  }
  
              }
              for (int i = 0; i < n; i++) {
                  int x = a[i];
                  int root = dsu.find(i);
                  list.clear();
                  for (IntegerIterator iterator = primes.iterator(x + 1); iterator.hasNext(); ) {
                      int p = iterator.next();
                      if (reg[p] == -1) {
                          continue;
                      }
                      list.add(dsu.find(reg[p]));
                      sets[root].add(dsu.find(reg[p]));
                  }
                  list.unique();
                  int[] data = list.getData();
                  int size = list.size();
                  for (int j = 0; j < size; j++) {
                      for (int t = j + 1; t < size; t++) {
                          em.add(id(data[j], data[t]));
                      }
                  }
              }
              for (int i = 0; i < q; i++) {
                  int s = in.ri() - 1;
                  int t = in.ri() - 1;
                  s = dsu.find(s);
                  t = dsu.find(t);
                  if (s == t) {
                      out.println(0);
                  } else {
                      if (sets[s].contains(t) || sets[t].contains(s) || em.contain(id(s, t))) {
                          out.println(1);
                      } else {
                          out.println(2);
                      }
                  }
              }
          }
  
      }
  
      static class FastOutput implements AutoCloseable, Closeable, Appendable {
          private static final int THRESHOLD = 32 << 10;
          private OutputStream writer;
          private StringBuilder cache = new StringBuilder(THRESHOLD * 2);
          private static Field stringBuilderValueField;
          private char[] charBuf = new char[THRESHOLD * 2];
          private byte[] byteBuf = new byte[THRESHOLD * 2];
  
          static {
              try {
                  stringBuilderValueField = StringBuilder.class.getSuperclass().getDeclaredField("value");
                  stringBuilderValueField.setAccessible(true);
              } catch (Exception e) {
                  stringBuilderValueField = null;
              }
              stringBuilderValueField = null;
          }
  
          public FastOutput append(CharSequence csq) {
              cache.append(csq);
              return this;
          }
  
          public FastOutput append(CharSequence csq, int start, int end) {
              cache.append(csq, start, end);
              return this;
          }
  
          private void afterWrite() {
              if (cache.length() < THRESHOLD) {
                  return;
              }
              flush();
          }
  
          public FastOutput(OutputStream writer) {
              this.writer = writer;
          }
  
          public FastOutput append(char c) {
              cache.append(c);
              afterWrite();
              return this;
          }
  
          public FastOutput append(int c) {
              cache.append(c);
              afterWrite();
              return this;
          }
  
          public FastOutput println(int c) {
              return append(c).println();
          }
  
          public FastOutput println() {
              return append('\n');
          }
  
          public FastOutput flush() {
              try {
                  if (stringBuilderValueField != null) {
                      try {
                          byte[] value = (byte[]) stringBuilderValueField.get(cache);
                          writer.write(value, 0, cache.length());
                      } catch (Exception e) {
                          stringBuilderValueField = null;
                      }
                  }
                  if (stringBuilderValueField == null) {
                      int n = cache.length();
                      if (n > byteBuf.length) {
                          //slow
                          writer.write(cache.toString().getBytes(StandardCharsets.UTF_8));
  //                writer.append(cache);
                      } else {
                          cache.getChars(0, n, charBuf, 0);
                          for (int i = 0; i < n; i++) {
                              byteBuf[i] = (byte) charBuf[i];
                          }
                          writer.write(byteBuf, 0, n);
                      }
                  }
                  writer.flush();
                  cache.setLength(0);
              } catch (IOException e) {
                  throw new UncheckedIOException(e);
              }
              return this;
          }
  
          public void close() {
              flush();
              try {
                  writer.close();
              } catch (IOException e) {
                  throw new UncheckedIOException(e);
              }
          }
  
          public String toString() {
              return cache.toString();
          }
  
      }
  
      static interface IntegerIterator {
          boolean hasNext();
  
          int next();
  
      }
  
      static class IntegerArrayList implements Cloneable {
          private int size;
          private int cap;
          private int[] data;
          private static final int[] EMPTY = new int[0];
  
          public int[] getData() {
              return data;
          }
  
          public IntegerArrayList(int cap) {
              this.cap = cap;
              if (cap == 0) {
                  data = EMPTY;
              } else {
                  data = new int[cap];
              }
          }
  
          public IntegerArrayList(int[] data) {
              this(0);
              addAll(data);
          }
  
          public IntegerArrayList(IntegerArrayList list) {
              this.size = list.size;
              this.cap = list.cap;
              this.data = Arrays.copyOf(list.data, size);
          }
  
          public IntegerArrayList() {
              this(0);
          }
  
          public void ensureSpace(int req) {
              if (req > cap) {
                  while (cap < req) {
                      cap = Math.max(cap + 10, 2 * cap);
                  }
                  data = Arrays.copyOf(data, cap);
              }
          }
  
          public void add(int x) {
              ensureSpace(size + 1);
              data[size++] = x;
          }
  
          public void addAll(int[] x) {
              addAll(x, 0, x.length);
          }
  
          public void addAll(int[] x, int offset, int len) {
              ensureSpace(size + len);
              System.arraycopy(x, offset, data, size, len);
              size += len;
          }
  
          public void addAll(IntegerArrayList list) {
              addAll(list.data, 0, list.size);
          }
  
          public void sort() {
              if (size <= 1) {
                  return;
              }
              Randomized.shuffle(data, 0, size);
              Arrays.sort(data, 0, size);
          }
  
          public void unique() {
              if (size <= 1) {
                  return;
              }
  
              sort();
              int wpos = 1;
              for (int i = 1; i < size; i++) {
                  if (data[i] != data[wpos - 1]) {
                      data[wpos++] = data[i];
                  }
              }
              size = wpos;
          }
  
          public int size() {
              return size;
          }
  
          public int[] toArray() {
              return Arrays.copyOf(data, size);
          }
  
          public void clear() {
              size = 0;
          }
  
          public String toString() {
              return Arrays.toString(toArray());
          }
  
          public boolean equals(Object obj) {
              if (!(obj instanceof IntegerArrayList)) {
                  return false;
              }
              IntegerArrayList other = (IntegerArrayList) obj;
              return SequenceUtils.equal(data, 0, size - 1, other.data, 0, other.size - 1);
          }
  
          public int hashCode() {
              int h = 1;
              for (int i = 0; i < size; i++) {
                  h = h * 31 + Integer.hashCode(data[i]);
              }
              return h;
          }
  
          public IntegerArrayList clone() {
              IntegerArrayList ans = new IntegerArrayList();
              ans.addAll(this);
              return ans;
          }
  
      }
  
      static class Randomized {
          public static void shuffle(int[] data, int from, int to) {
              to--;
              for (int i = from; i <= to; i++) {
                  int s = nextInt(i, to);
                  int tmp = data[i];
                  data[i] = data[s];
                  data[s] = tmp;
              }
          }
  
          public static int nextInt(int l, int r) {
              return RandomWrapper.INSTANCE.nextInt(l, r);
          }
  
      }
  
      static class Hasher {
          private final long time = System.nanoTime() + System.currentTimeMillis() * 31L;
  
          public int shuffle(long z) {
              z += time;
              z = (z ^ (z >>> 33)) * 0x62a9d9ed799705f5L;
              return (int) (((z ^ (z >>> 28)) * 0xcb24d0a5c88c35b3L) >>> 32);
          }
  
          public int hash(long x) {
              return shuffle(x);
          }
  
      }
  
      static class RandomWrapper {
          private Random random;
          public static final RandomWrapper INSTANCE = new RandomWrapper();
  
          public RandomWrapper() {
              this(new Random());
          }
  
          public RandomWrapper(Random random) {
              this.random = random;
          }
  
          public RandomWrapper(long seed) {
              this(new Random(seed));
          }
  
          public int nextInt(int l, int r) {
              return random.nextInt(r - l + 1) + l;
          }
  
      }
  
      static class DigitUtils {
          public static long INT_TO_LONG_MASK = (1L << 32) - 1;
  
          private DigitUtils() {
          }
  
          public static boolean isMultiplicationOverflow(long a, long b, long limit) {
              if (limit < 0) {
                  limit = -limit;
              }
              if (a < 0) {
                  a = -a;
              }
              if (b < 0) {
                  b = -b;
              }
              if (a == 0 || b == 0) {
                  return false;
              }
              //a * b > limit => a > limit / b
              return a > limit / b;
          }
  
          public static long asLong(int high, int low) {
              return (((long) high) << 32) | (((long) low) & INT_TO_LONG_MASK);
          }
  
      }
  
      static class LongHashSet {
          private int now;
          private int[] slot;
          private int[] version;
          private int[] next;
          private long[] keys;
          private int alloc;
          private boolean[] removed;
          private int mask;
          private int size;
          private boolean rehash;
          private Hasher hasher = new Hasher();
  
          public LongHashSet(int cap, boolean rehash) {
              now = 1;
              this.mask = (1 << (32 - Integer.numberOfLeadingZeros(cap - 1))) - 1;
              this.rehash = rehash;
              slot = new int[mask + 1];
              version = new int[slot.length + 1];
              next = new int[cap + 1];
              keys = new long[cap + 1];
              removed = new boolean[cap + 1];
          }
  
          private void access(int i) {
              if (version[i] != now) {
                  version[i] = now;
                  slot[i] = 0;
              }
          }
  
          private void doubleCapacity() {
              int newSize = Math.max(next.length + 10, next.length * 2);
              next = Arrays.copyOf(next, newSize);
              keys = Arrays.copyOf(keys, newSize);
              removed = Arrays.copyOf(removed, newSize);
          }
  
          public void alloc() {
              alloc++;
              if (alloc >= next.length) {
                  doubleCapacity();
              }
              next[alloc] = 0;
              removed[alloc] = false;
              size++;
          }
  
          private int hash(long x) {
              return hasher.hash(x);
          }
  
          public void add(long x) {
              int h = hash(x);
              int s = h & mask;
              access(s);
              if (slot[s] == 0) {
                  alloc();
                  slot[s] = alloc;
                  keys[alloc] = x;
                  return;
              } else {
                  int index = findIndexOrLastEntry(s, x);
                  if (keys[index] != x) {
                      alloc();
                      next[index] = alloc;
                      keys[alloc] = x;
                  }
              }
              if (rehash && size >= slot.length) {
                  rehash();
              }
          }
  
          private void rehash() {
              int[] newSlots = new int[Math.max(16, slot.length * 2)];
              int[] newVersions = new int[newSlots.length];
              int newMask = newSlots.length - 1;
              for (int i = 0; i < slot.length; i++) {
                  access(i);
                  if (slot[i] == 0) {
                      continue;
                  }
                  int head = slot[i];
                  while (head != 0) {
                      int n = next[head];
                      int s = hash(keys[head]) & newMask;
                      next[head] = newSlots[s];
                      newSlots[s] = head;
                      head = n;
                  }
              }
              this.slot = newSlots;
              this.version = newVersions;
              now = 0;
              this.mask = newMask;
          }
  
          public boolean contain(long x) {
              int h = hash(x);
              int s = h & mask;
              access(s);
              if (slot[s] == 0) {
                  return false;
              }
              return keys[findIndexOrLastEntry(s, x)] == x;
          }
  
          private int findIndexOrLastEntry(int s, long x) {
              int iter = slot[s];
              while (keys[iter] != x) {
                  if (next[iter] != 0) {
                      iter = next[iter];
                  } else {
                      return iter;
                  }
              }
              return iter;
          }
  
          public LongIterator iterator() {
              return new LongIterator() {
                  int index = 1;
  
  
                  public boolean hasNext() {
                      while (index <= alloc && removed[index]) {
                          index++;
                      }
                      return index <= alloc;
                  }
  
  
                  public long next() {
                      if (!hasNext()) {
                          throw new IllegalStateException();
                      }
                      return keys[index++];
                  }
              };
          }
  
          public String toString() {
              LongIterator iterator = iterator();
              StringBuilder builder = new StringBuilder("{");
              while (iterator.hasNext()) {
                  builder.append(iterator.next()).append(',');
              }
              if (builder.charAt(builder.length() - 1) == ',') {
                  builder.setLength(builder.length() - 1);
              }
              builder.append('}');
              return builder.toString();
          }
  
      }
  
      static class FastInput {
          private final InputStream is;
          private byte[] buf = new byte[1 << 13];
          private int bufLen;
          private int bufOffset;
          private int next;
  
          public FastInput(InputStream is) {
              this.is = is;
          }
  
          public void populate(int[] data) {
              for (int i = 0; i < data.length; i++) {
                  data[i] = readInt();
              }
          }
  
          private int read() {
              while (bufLen == bufOffset) {
                  bufOffset = 0;
                  try {
                      bufLen = is.read(buf);
                  } catch (IOException e) {
                      bufLen = -1;
                  }
                  if (bufLen == -1) {
                      return -1;
                  }
              }
              return buf[bufOffset++];
          }
  
          public void skipBlank() {
              while (next >= 0 && next <= 32) {
                  next = read();
              }
          }
  
          public int ri() {
              return readInt();
          }
  
          public int[] ri(int n) {
              int[] ans = new int[n];
              populate(ans);
              return ans;
          }
  
          public int readInt() {
              boolean rev = false;
  
              skipBlank();
              if (next == '+' || next == '-') {
                  rev = next == '-';
                  next = read();
              }
  
              int val = 0;
              while (next >= '0' && next <= '9') {
                  val = val * 10 - next + '0';
                  next = read();
              }
  
              return rev ? val : -val;
          }
  
      }
  
      static class IntegerMultiWayStack {
          private int[] values;
          private int[] next;
          private int[] heads;
          private int alloc;
          private int stackNum;
  
          public IntegerIterator iterator(final int queue) {
              return new IntegerIterator() {
                  int ele = heads[queue];
  
  
                  public boolean hasNext() {
                      return ele != 0;
                  }
  
  
                  public int next() {
                      int ans = values[ele];
                      ele = next[ele];
                      return ans;
                  }
              };
          }
  
          private void doubleCapacity() {
              int newSize = Math.max(next.length + 10, next.length * 2);
              next = Arrays.copyOf(next, newSize);
              values = Arrays.copyOf(values, newSize);
          }
  
          public void alloc() {
              alloc++;
              if (alloc >= next.length) {
                  doubleCapacity();
              }
              next[alloc] = 0;
          }
  
          public boolean isEmpty(int qId) {
              return heads[qId] == 0;
          }
  
          public IntegerMultiWayStack(int qNum, int totalCapacity) {
              values = new int[totalCapacity + 1];
              next = new int[totalCapacity + 1];
              heads = new int[qNum];
              stackNum = qNum;
          }
  
          public void addLast(int qId, int x) {
              alloc();
              values[alloc] = x;
              next[alloc] = heads[qId];
              heads[qId] = alloc;
          }
  
          public String toString() {
              StringBuilder builder = new StringBuilder();
              for (int i = 0; i < stackNum; i++) {
                  if (isEmpty(i)) {
                      continue;
                  }
                  builder.append(i).append(": ");
                  for (IntegerIterator iterator = iterator(i); iterator.hasNext(); ) {
                      builder.append(iterator.next()).append(",");
                  }
                  if (builder.charAt(builder.length() - 1) == ',') {
                      builder.setLength(builder.length() - 1);
                  }
                  builder.append('\n');
              }
              return builder.toString();
          }
  
      }
  
      static class MaximumFactorMinimumNumber {
          private static int[] primes = new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53};
  
          public static long[] maximumPrimeFactor(long n) {
              long[] ans = new long[2];
              ans[0] = 1;
              for (int i = 0; i < primes.length; i++) {
                  if (DigitUtils.isMultiplicationOverflow(ans[0], primes[i], n)) {
                      break;
                  }
                  ans[0] *= primes[i];
                  ans[1]++;
              }
              return ans;
          }
  
      }
  
      static class Factorization {
          public static IntegerMultiWayStack factorizeRangePrime(int n) {
              int maxFactorCnt = (int) MaximumFactorMinimumNumber.maximumPrimeFactor(n)[1];
              IntegerMultiWayStack stack = new IntegerMultiWayStack(n + 1, n * maxFactorCnt);
              boolean[] isComp = new boolean[n + 1];
              for (int i = 2; i <= n; i++) {
                  if (isComp[i]) {
                      continue;
                  }
                  for (int j = i; j <= n; j += i) {
                      isComp[j] = true;
                      stack.addLast(j, i);
                  }
              }
              return stack;
          }
  
      }
  
      static class DSU {
          protected int[] p;
          public int[] size;
          protected int n;
  
          public DSU(int n) {
              p = new int[n];
              size = new int[n];
          }
  
          public void init() {
              init(p.length);
          }
  
          public void init(int n) {
              this.n = n;
              for (int i = 0; i < n; i++) {
                  p[i] = i;
                  size[i] = 1;
              }
          }
  
          public final int find(int a) {
              if (p[a] == p[p[a]]) {
                  return p[a];
              }
              find(p[a]);
              preAccess(a);
              return p[a] = p[p[a]];
          }
  
          protected void preAccess(int a) {
  
          }
  
          protected void preMerge(int a, int b) {
              size[a] += size[b];
          }
  
          public final void merge(int a, int b) {
              a = find(a);
              b = find(b);
              if (a == b) {
                  return;
              }
  
              if (size[a] < size[b]) {
                  int tmp = a;
                  a = b;
                  b = tmp;
              }
              preMerge(a, b);
              p[b] = a;
          }
  
          public String toString() {
              return Arrays.toString(Arrays.copyOf(p, n));
          }
  
      }
  
      static class SequenceUtils {
          public static boolean equal(int[] a, int al, int ar, int[] b, int bl, int br) {
              if ((ar - al) != (br - bl)) {
                  return false;
              }
              for (int i = al, j = bl; i <= ar; i++, j++) {
                  if (a[i] != b[j]) {
                      return false;
                  }
              }
              return true;
          }
  
      }
  
      static interface LongIterator {
          boolean hasNext();
  
          long next();
  
      }
  }
  
  