import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void scan(T...)(ref T a) {
    string[] ss = readln.split;
    foreach (i, t; T) a[i] = ss[i].to!t;
}
T read(T)() { return readln.chomp.to!T; }
T[] reads(T)() { return readln.split.to!(T[]); }
alias readint = read!int;
alias readints = reads!int;

const MOD = 10^^9 + 7;

int[int] fac(int n) {
    assert(n > 1);

    int[int] ps;
    while (n % 2 == 0) {
        ps[2]++;
        n /= 2;
    }
    for (int i = 3; i * i <= n; i += 2) {
        while (n % i == 0) {
            ps[i]++;
            n /= i;
        }
    }
    if (n > 1) ps[n]++;
    return ps;
}

long calc(int n, int m) {
    if (m == 1) return 1;

    initFactTable(n * 3);

    import std.exception;
    enforce(n > 1);

    long ans = 1;
    foreach (v; fac(m).values) {
        // v 個の素因数と n - 1 個の仕切りの並べ方
        ans = (ans * nck(v + n - 1, n - 1)) % MOD;
    }
    return ans;
}

void main() {
    int n, m; scan(n, m);
    writeln(calc(n, m));
}

long[] fact; // 階乗
long[] factInv; // 階乗の逆元

void initFactTable(int n) {
    fact = new long[n + 1];
    fact[0] = 1;
    for (int i = 1; i <= n; i++)
        fact[i] = i * fact[i - 1] % MOD;

    factInv = new long[n + 1];
    factInv[n] = modPow(fact[n], MOD - 2, MOD);
    for (int i = n - 1; i >= 0; i--)
        factInv[i] = factInv[i + 1] * (i + 1) % MOD;
}

long modPow(long x, long k, long m) {
    if (k == 0) return 1;
    if (k % 2 == 0) return modPow(x * x % m, k / 2, m);
    return x * modPow(x, k - 1, m) % m;
}

long nck(int n, int k) {
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return (fact[n] * factInv[k] % MOD) * factInv[n - k] % MOD;
}
