Problem:
Score : 400 points

Problem Statement

You are given positive integers N and M.

How many sequences a of length N consisting of positive integers satisfy a_1 \times a_2 \times ... \times a_N = M? Find the count modulo 10^9+7.

Here, two sequences a' and a'' are considered different when there exists some i such that a_i' \neq a_i''.

Constraints

All values in input are integers.

1 \leq N \leq 10^5

1 \leq M \leq 10^9

Input

Input is given from Standard Input in the following format:

N M

Output

Print the number of the sequences consisting of positive integers that satisfy the condition, modulo 10^9 + 7.

Sample Input 1

2 6

Sample Output 1

4

Four sequences satisfy the condition: \{a_1, a_2\} = \{1, 6\}, \{2, 3\}, \{3, 2\} and \{6, 1\}.

Sample Input 2

3 12

Sample Output 2

18

Sample Input 3

100000 1000000000

Sample Output 3

957870001

Solution in C# (Mono 4.6.2.0) (judge verdict: Runtime Error)

using MathX;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ABC110D___Factorization
{
    public class Program
    {
    
        public static readonly int MOD = (int)Math.Pow(10, 9) + 7;

        public static void Main(string[] args)
        {
            checked { 
                string[] line = Console.ReadLine().Trim().Split(' ');
                int n = int.Parse(line[0]);
                int m = int.Parse(line[1]);

                List<int> primes = MathX.MathX.PrimeFactor(m).Select(x => (int)x).ToList();
                Dictionary<int, int> primesDic = new Dictionary<int, int>();
                foreach (int i in primes)
                {
                    if (primesDic.ContainsKey(i)) primesDic[i]++;
                    else primesDic.Add(i, 1);
                }

                long rlt = 1;

                foreach(KeyValuePair<int,int> i in primesDic)
                {
                    rlt *= (int)MathX.MathX.Combination(i.Value + n - 1, i.Value, MOD) % MOD;
                }

                Console.WriteLine(rlt % MOD);
            }
        }
    }

}

namespace MathX
{
    public class MathX
    {
        //●最小公倍数
        public static long Lcm(long a, long b)
        {
            return a / Gcd(a, b) * b;
        }

        //●最大公約数
        public static long Gcd(long a, long b)
        {
            if (a < b)
                return Gcd(b, a);  // 引数を入替えて自分を呼び出す
            if (b == 0) return a; //一方が0の場合は、もう片方の数自身がGCD
            long d = 0;
            do
            {
                d = a % b;
                a = b;
                b = d;
            } while (d != 0);
            return a;
        }

        //●素因数分解（ポラード・ロー素因数分解法）
        public static IEnumerable<long> PrimeFactor(long n)
            {
                while (n > 1)
                {
                    long factor = GetFactor(n);
                    yield return factor;
                    n = n / factor;
                }
            }

         private static long GetFactor(long n, int seed = 1)
            {
                if (n % 2 == 0)  return 2;
                if (IsPrime(n))  return n;
                long x = 2, y = 2, d = 1;
                long count = 0;
                while (d == 1)
                {
                    count++;
                    x = f(x, n, seed);
                    y = f(f(y, n, seed), n, seed);
                    d = Gcd(Math.Abs(x - y), n);
                }
                if (d == n)
                    // 見つからなかった、乱数発生のシードを変えて再挑戦。
                    return GetFactor(n, seed + 1);
                // 素数でない可能性もあるので、再度呼び出す
                return GetFactor(d);
            }

            private static int[] seeds = new int[] { 3, 5, 7, 11, 13, 17 };
            private static long f(long x, long n, int seed)
            {
                return (seeds[seed % 6] * x + seed) % n;
            }


        //●素数判定
        public static bool IsPrime(long number)
        {
            long boundary = (long)Math.Floor(Math.Sqrt(number));

            if (number == 1)  return false;
            if (number == 2)  return true;

            for (long i = 2; i <= boundary; ++i)
            {
                if (number % i == 0) return false;
            }
            return true;
        }

        //●階乗
        public static long Factorial(long n, long mod = 0)
        {
            checked
            {
                if (n == 0)  return 1L;
                if (mod == 0)
                { return n * Factorial(n - 1); }
                else
                { return n * Factorial(n - 1, mod) % mod; }           
            }
        }

        //●組み合わせの数
        public static long Combination(long n,long r, long mod = 0)
        {
            checked
            {
                long ans = 1;
                if (r > n / 2) return Combination(n, n - r, mod);//計算量を減らす(5C4 = 5C1)
                long div = 1;
                for (int i = 0; i < r; i++)
                {
                    ans *= n - i;
                    div *= i + 1;
                    if (mod != 0)
                    {
                        ans %= mod;
                        div %= mod;
                    }
                }

                if (mod != 0)
                {
                    ans *= Powmod(div, mod - 2, mod);
                    return ans % mod;
                }
                else return ans/div;

            }
        }


        //●mod下での累乗計算
        public static  long Powmod(long a, long p,long mod)
        {
            checked
            {
                long ans = 1;
                long mul = a;
                for (; p > 0; p >>= 1, mul = (mul * mul) % mod)
                {
                    if ((p & 1) == 1) ans = (ans * mul) % mod;
                }
                return ans;
            }
        }
    }

}