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# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using static Scanner;

class Solver
{
    const int MAX = 110000;
    const int MOD = 1000000007;
    static long[] Fac = new long[MAX], Finv = new long[MAX], Inv = new long[MAX];

    static void Main(string[] args) {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) {AutoFlush = false});
        Solve(new Reader());
        Console.Out.Flush();
    }

    static void Solve(Reader sc) {
        var (N, M) = sc.Int;
        COMini();
        var primeFactors = PrimeFactorization(M);
        long result = 1;
        foreach (var p in primeFactors) {
            var num = p.count;
            long temp = COM(num + N - 1, N - 1);
            result = result * temp % MOD;
        }
        Console.WriteLine(result);
    }

    static void COMini() {
        Fac[0] = Fac[1] = 1;
        Finv[0] = Finv[1] = 1;
        Inv[1] = 1;
        for (int i = 2; i < MAX; i++) {
            Fac[i] = Fac[i - 1] * i % MOD;
            Inv[i] = MOD - Inv[MOD % i] * (MOD / i) % MOD;
            Finv[i] = Finv[i - 1] * Inv[i] % MOD;
        }
    }

    static long COM(int N, int K) {
        if (N < K) return 0;
        if (N < 0 || K < 0) return 0;
        return Fac[N] * (Finv[K] * Finv[N - K] % MOD) % MOD;
    }

    static List<(int prime, int count)> PrimeFactorization(int N) {
        var ret = new List<(int, int)>();
        for (int i = 2; i * i <= N; i++) {
            if (N % i != 0) continue;
            var count = 0;
            while (N % i == 0) {
                count++;
                N /= i;
            }

            ret.Add((i, count));
        }
        if (N != 1) ret.Add((N, 1));
        return ret;
    }
}

public readonly struct Reader
{
    public readonly Cin<int> Int;
    public readonly Cin<long> Long;
    public readonly Cin<double> Double;
    public readonly Cin<string> Str;
}

public readonly struct Cin<T>
{
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static implicit operator T(Cin<T> _) => Sc;
    private static T Sc => Scan<T>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T[] Array(int length) {
        var array = new T[length];
        for (int i = 0; i < array.Length; i++) array[i] = Scan<T>();
        return array;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T[,] Array2D(int xLen, int yLen) {
        var array = new T[xLen, yLen];
        for (int i = 0; i < xLen; ++i)
        for (int j = 0; j < xLen; ++j)
            array[i, j] = Scan<T>();
        return array;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Deconstruct(out T a, out T b) => (a, b) = (Sc, Sc);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Deconstruct(out T a, out T b, out T c) => (a, b, c) = (Sc, Sc, Sc);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Deconstruct(out T a, out T b, out T c, out T d) => (a, b, c, d) = (Sc, Sc, Sc, Sc);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Deconstruct(out T a, out T b, out T c, out T d, out T e) => (a, b, c, d, e) = (Sc, Sc, Sc, Sc, Sc);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void Deconstruct(out T a, out T b, out T c, out T d, out T e, out T f) => (a, b, c, d, e, f) = (Sc, Sc, Sc, Sc, Sc, Sc);
}

public static class Scanner
{
    const int BUFFER_SIZE = 1024;
    const int CHAR_BEGIN = 33, CHAR_END = 126;
    const int CHAR_ZERO = 48, CHAR_NINE = 57;
    static readonly Stream stdin;
    static readonly byte[] buffer;
    static int size, p;
    static bool isEof;
    static Scanner() {
        stdin = Console.OpenStandardInput();
        buffer = new byte[BUFFER_SIZE];
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static byte Read() {
        if (isEof) throw new EndOfStreamException();
        if (p < size) return buffer[p++];
        p = 0;
        if ((size = stdin.Read(buffer, 0, BUFFER_SIZE)) > 0) return buffer[p++];
        isEof = true;
        return 0;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static char Next() {
        byte b;
        do b = Read();
        while (!(CHAR_BEGIN <= b && b <= CHAR_END));
        return (char) b;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static string Str() {
        var sb = new StringBuilder();
        for (var c = Next(); CHAR_BEGIN <= c && c <= CHAR_END; c = (char) Read()) {
            sb.Append(c);
        }
        return sb.ToString();
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static int Int() {
        int temp = 0;
        for (var c = Next(); CHAR_ZERO <= c && c <= CHAR_NINE; c = (char) Read()) {
            temp = temp * 10 + c - CHAR_ZERO;
        }
        return temp;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static long Long() {
        long temp = 0;
        for (var c = Next(); CHAR_ZERO <= c && c <= CHAR_NINE; c = (char) Read()) {
            temp = temp * 10 + c - CHAR_ZERO;
        }
        return temp;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static double Double() => double.Parse(Str(), CultureInfo.InvariantCulture);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static T Scan<T>() {
        return default(T) switch {
            int _ => (T) (object) Int(),
            long _ => (T) (object) Long(),
            double _ => (T) (object) Double(),
            string _ => (T) (object) Str(),
            _ => throw new NotSupportedException()
        };
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static (T1, T2) Scan<T1, T2>() => (Scan<T1>(), Scan<T2>());
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static (T1, T2, T3) Scan<T1, T2, T3>() => (Scan<T1>(), Scan<T2>(), Scan<T3>());
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static (T1, T2, T3, T4) Scan<T1, T2, T3, T4>() => (Scan<T1>(), Scan<T2>(), Scan<T3>(), Scan<T4>());
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static (T1, T2, T3, T4, T5) Scan<T1, T2, T3, T4, T5>() => (Scan<T1>(), Scan<T2>(), Scan<T3>(), Scan<T4>(), Scan<T5>());
}