#include <functional>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <tuple>
#include <set>
#include <map>

#define FOR0(var, max) for (ul (var) = 0; (var) < (max); ++(var))
#define FORi(var, min, max) for (ul (var) = (min); (var) < (max); ++(var))
#define FORi_INV(var, min, max) for (ul (var) = (max) - 1; (var) + 1 > (min); --(var))
#define FORITER(var, iter) for (auto (iter) = (var).begin(); (iter) != (var).end(); (iter)++)
#define FORITER_INV(var, iter) for (auto (iter) = (var).rbegin(); (iter) != (var).rend(); (iter)++)

#define LTLT(a, b, c) (((a) < (b)) && ((b) < (c)))
#define LELT(a, b, c) (((a) <= (b)) && ((b) < (c)))
#define LTLE(a, b, c) (((a) < (b)) && ((b) <= (c)))
#define LELE(a, b, c) (((a) <= (b)) && ((b) <= (c)))

using namespace std;

using uc = unsigned char;
using ui = unsigned int;
using ul = unsigned long long int;

using sc = signed char;
using si = signed int;
using sl = signed long long int;

template <class T>
T gcd(T a, T b) {
  while (b) {
    T t = a % b;
    a = b;
    b = t;
  }
  return a;
}

bool isprime(const ul& n) {
  if (n < 2 || n % 2 == 0) {
    return false;
  }
  for (ul i = 1; i * i < n; i += 2) {
    if (n % i == 0) {
      return false;
    }
  }
  return true;
}

set<ul> divisors(const ul& n) {
  set<ul> div;
  for (ul i = 1; i * i <= n; i++) {
    if (n % i == 0) {
      div.insert(i);
      if (n / i != i) {
        div.insert(n / i);
      }
    }
  }
  if (n == 1) {
    div.insert(1);
  }
  return div;
}

template <class T>
set<T> set_intersection(const set<T>& X, const set<T>& Y) {
  set<T> ret;
  std::set_intersection(X.begin(), X.end(), Y.begin(), Y.end(), inserter(ret, ret.end()));
  return move(ret);
}

/* (identity element, operation) */
template <class T>
using Monoid = pair<T, function<T(T, T)>>;

template <class T, ui K>
class SegmentTree {
  const Monoid<T> monoid;
  const ul N = (1 << K);
  T tree[2 * (1 << K) - 1];

  inline ui parent(ui i) const {
    if (i == 0) {
      return 0;
    }
    return (i - 1) / 2;
  }

  inline ui leaf(ui i) const {
    return i + N - 1;
  }

  inline ui left(ui i) const {
    return i * 2 + 1;
  }

  inline ui right(ui i) const {
    return i * 2 + 2;
  }

  inline bool is_leaf(ui i) const {
    return (N - 1 <= i);
  }

  inline bool is_root(ui i) const {
    return i == 0;
  }

  inline ui root(void) const {
    return 0;
  }

public:
  /* Initialize Segment Tree with Monoid `_monoid` */
  SegmentTree(const Monoid<T>& _monoid, const T& default_value) : monoid(_monoid) {
    queue<ui> Q;
    FOR0(i, N) {
      tree[leaf(i)] = default_value;
      if (i % 2 == 0) {
        Q.push(parent(leaf(i)));
      }
    }
    while (!Q.empty()) {
      auto v = Q.front();
      Q.pop();
      tree[v] = monoid.second(tree[left(v)], tree[right(v)]);
      if (!is_root(v)) {
        if (left(parent(v)) == v) {
          Q.push(parent(v));
        }
      }
    }
  }

  SegmentTree(const Monoid<T>& _monoid)
      : SegmentTree(_monoid, _monoid.first) {
  }

  void update(ui i, T x) {
    ui cur = leaf(i);
    tree[cur] = x;
    while (!is_root(cur)) {
      cur = parent(cur);
      tree[cur] = monoid.second(tree[left(cur)], tree[right(cur)]);
    }
  }

  // [a, b)
  T query(ui a, ui b) {
    if (a == b) {
      throw invalid_argument("[a, a)");
    }
    T resL = monoid.first;
    T resR = monoid.first;
    ui vL = leaf(a);
    ui vR = leaf(b - 1);
    while (vL != vR) {
      if (right(parent(vL)) == vL) {
        resL = monoid.second(resL, tree[vL]);
        vL = vL + 1;
      }
      if (vL == vR) {
        break;
      }
      if (left(parent(vR)) == vR) {
        resR = monoid.second(tree[vR], resR);
        vR = vR - 1;
      }
      vL = parent(vL);
      vR = parent(vR);
    }
    resL = monoid.second(resL, tree[vL]);
    return monoid.second(resL, resR);
  }
};

static ul ABMAX = 1000000000000ULL;
static ul A, B;

void solve(void) {
  if (A >= B) {
    swap(A, B);
  }

  set<ul> div = set_intersection(divisors(A), divisors(B));

  ul cur = 1;
  ul i = 0;
  FORITER(div, it) {
    if (gcd(*it, cur) == 1) {
      i++;
      cur *= *it;
    }
  }
  cout << i << endl;
}

int main(void) {
  cin >> A >> B;
  solve();
  return 0;
}

Measured memory_bytes: 1152