Problem:
Score : 400 points

Problem Statement

Given are positive integers A and B.

Let us choose some number of positive common divisors of A and B.

Here, any two of the chosen divisors must be coprime.

At most, how many divisors can we choose?

Definition of common divisor

An integer d is said to be a common divisor of integers x and y when d divides both x and y.

Definition of being coprime

Integers x and y are said to be coprime when x and y have no positive common divisors other than 1.

Definition of dividing

An integer x is said to divide another integer y when there exists an integer \alpha such that y = \alpha x.

Constraints

All values in input are integers.

1 \leq A, B \leq 10^{12}

Input

Input is given from Standard Input in the following format:

A B

Output

Print the maximum number of divisors that can be chosen to satisfy the condition.

Sample Input 1

12 18

Sample Output 1

3

12 and 18 have the following positive common divisors: 1, 2, 3, and 6.

1 and 2 are coprime, 2 and 3 are coprime, and 3 and 1 are coprime, so we can choose 1, 2, and 3, which achieve the maximum result.

Sample Input 2

420 660

Sample Output 2

4

Sample Input 3

1 2019

Sample Output 3

1

1 and 2019 have no positive common divisors other than 1.

Solution in C# (Mono 4.6.2.0) (judge verdict: Time Limit Exceeded)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;



class Program 
{
    const int MOD = 1000000007;
    const int INF = 1 << 30;



    static void Main(string[] args) 
    {
        Solve();
    }



    static void Solve() 
    {
        Scaner cin = new Scaner();
        write wr = new write();
        Math2 mmath = new Math2();
        //ここから

        var o = cin.LongM;
        long A = o[0];
        long B = o[1];

        var N = mmath.GCD(A, B);
        var X = mmath.PrimeFactorization(N);
        long ans = X.Count();

        wr.wri(ans + 1);




    }


}






//b-aで降順

    //priority queue
class PriorityQueue<T> 
{
    private readonly List<T> heap;
    private readonly Comparison<T> compare;
    private int size;
    public PriorityQueue() : this(Comparer<T>.Default) {} 
    public PriorityQueue(IComparer<T> comparer) : this(16, comparer.Compare) { }
    public PriorityQueue(Comparison<T> comparison) : this(16, comparison) { }
    public PriorityQueue(int capacity, Comparison<T> comparison)
    {
        this.heap = new List<T>(capacity);
        this.compare = comparison;
    }
    public void Enqueue(T item)
    {
        this.heap.Add(item);
        var i = size++;
        while (i > 0)
        {
            var p = (i - 1) >> 1;
            if (compare(this.heap[p], item) <= 0)
                break;
            this.heap[i] = heap[p];
            i = p;
        }
        this.heap[i] = item;

    }
    public T Dequeue()
    {
        var ret = this.heap[0];
        var x = this.heap[--size];
        var i = 0;
        while ((i << 1) + 1 < size)
        {
            var a = (i << 1) + 1;
            var b = (i << 1) + 2;
            if (b < size && compare(heap[b], heap[a]) < 0) a = b;
            if (compare(heap[a], x) >= 0)
                break;
            heap[i] = heap[a];
            i = a;
        }
        heap[i] = x;
        heap.RemoveAt(size);
        return ret;
    }
    public T Peek() { return heap[0]; }
    public int Count { get { return size; } }
    public bool Any() { return size > 0; }
}


 public class Math2
{
    public long[] Fact;  //Nまでの階乗
    public long[] invFact;  //階乗の逆元

    //Nまでの階乗をセットしておく
    public void FactoricalModSet(long N,long MOD=1000000007)
    {
        Fact = new long[N + 1];
        invFact = new long[N + 1];

        Fact[0] = 1;
        for(long i = 1; i <= N; ++i)
        {
            Fact[i] = Fact[i - 1] * i%MOD;
        }
        invFact[N] = pow(Fact[N], MOD - 2);

        for (long i = N; i > 0; --i)
        {
            invFact[i - 1] = invFact[i] * i%MOD;
        }

    }

    //nCr 引数:n r (mod)
    public long nCr(long n,long r,long MOD=1000000007)
    {
        return (Fact[n] * invFact[r] % MOD * invFact[n-r]%MOD);
    }

    //階乗(O(logN)) 引数:底x n乗　(MOD)
    public long pow(long x,long n,long MOD = 1000000007)
    {
        long res = 1;
        while (n > 0)
        {
            if ((n & 1) != 0) res = res * x % MOD;
            x = x * x % MOD;
            n >>= 1;
        }
        return res;
    }

    //最大公約数 引数:整数x,y
    public long GCD(long x, long y)
    {
        if (y == 0) return x;
        return GCD(y, x % y);
    }
    //最小公倍数 引数:整数x,y
    public long LCM(long x, long y)
    {
        return x * y / GCD(x, y);
    }

    //素因数分解 引数:整数N
    public Dictionary<long,int > PrimeFactorization(long N)
    {
        var ret = new Dictionary<long,int>();

        for(int i = 2; i*i <= N; ++i)
        {
            int cnt = 0;
            while (N % i == 0)
            {
                cnt++;
                N /= i;
            }
            if (cnt != 0) ret[i] = cnt;

        }
        if (N >= 2)ret[N]=1;

        return ret;

    }


}


    
   


class Scaner
{
    public string Str => Console.ReadLine();

    public string[] StrM => Str.Split(' ');

    public long[] LongM => StrM.Select(long.Parse).ToArray();
    public int[] IntM => StrM.Select(int.Parse).ToArray();
    public char[] CharM => Str.ToArray();
    public long Long1 => LongM[0];
    public int Int1 => IntM[0];
    
}



class write
{
    public  void wri<T>(T x)
    {
        Console.WriteLine(x);
    }
}