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 Rust (1.15.1) (judge verdict: Time Limit Exceeded)

use std::io::*;
use std::ops::*;
use std::str::FromStr;
use utils::*;

pub fn main() {
    let i = stdin();
    let mut o = Vec::new();
    run(i.lock(), &mut o);
    stdout().write_all(&o).unwrap();
}

fn run<R: BufRead, W: Write>(i: R, o: &mut W) {
    let mut i = CpReader::new(i);
    let (n, m) = i.read2::<usize, usize>();
    writeln!(o, "{}", solve(n, m)).unwrap();
}
fn solve(n: usize, m: usize) -> usize {
    let mut count = ModInt::new(1);
    let mut cache = ModIntInverseCache::new();
    for c in factorization(m) {
        count *= to_count(n, c, &mut cache);
    }
    count.0
}

fn factorization(mut m: usize) -> Vec<usize> {
    let mut primes = Vec::new();

    let mut results = Vec::new();
    if m > 1 {
        for i in 2.. {
            let mut is_prime = true;
            for &p in &primes {
                if i % p == 0 {
                    is_prime = false;
                    break;
                }
            }
            if !is_prime {
                continue;
            }
            primes.push(i);
            let mut count = 0;
            while m % i == 0 {
                m /= i;
                count += 1;
            }
            if count != 0 {
                results.push(count);
            }
            if m == 1 {
                break;
            }
        }
    }
    results
}
fn to_count(n: usize, c: usize, cache: &mut ModIntInverseCache) -> ModInt {
    fn get_count(
        cs: &mut Vec<usize>,
        c_left: usize,
        c_next: usize,
        n: usize,
        cache: &mut ModIntInverseCache,
    ) -> ModInt {
        let mut count = ModInt::new(0);
        for c in 2..c_next + 1 {
            for g in 1..(c_left / c) + 1 {
                if n >= g {
                    cs.push(g);
                    count += get_count(cs, c_left - c * g, c - 1, n - g, cache) * comb(n, g, cache);
                    cs.pop();
                }
            }
        }
        if n >= c_left {
            cs.push(c_left);
            count += comb(n, c_left, cache);
            cs.pop();
        }
        count
    }
    let mut cs = Vec::new();
    get_count(&mut cs, c, c, n, cache)
}
fn comb(n: usize, m: usize, cache: &mut ModIntInverseCache) -> ModInt {
    let mut r = ModInt::new(1);
    for i in 0..m {
        r *= n - i;
        r *= cache.get(i + 1);
    }
    r
}

pub struct ModIntInverseCache(Vec<ModInt>);

impl ModIntInverseCache {
    pub fn new() -> Self {
        ModIntInverseCache(vec![ModInt::new(0)])
    }
    pub fn get(&mut self, n: usize) -> ModInt {
        assert!(n != 0);
        while self.0.len() <= n {
            let len = self.0.len();
            self.0.push(ModInt::new(len).inverse_element());
        }
        self.0[n]
    }
}

mod utils {
    use super::*;

    pub struct CpReader<R: BufRead> {
        r: R,
        s: String,
    }

    macro_rules! fn_read {
        { $f:ident($($t:ident),*) } => {
            #[allow(dead_code)]
            pub fn $f<$($t: FromStr),*>(&mut self) -> ($($t),*) {
                let i = &mut self.read_line().split(' ');
                ($(read_next::<$t,_>(i)),*)
            }
        };
    }

    impl<R: BufRead> CpReader<R> {
        pub fn new(r: R) -> Self {
            CpReader {
                r: r,
                s: String::new(),
            }
        }
        pub fn read_line(&mut self) -> &str {
            self.s.clear();
            self.r.read_line(&mut self.s).unwrap();
            self.s.trim()
        }

        fn_read! { read2(T1, T2) }
        fn_read! { read3(T1, T2, T3) }
        fn_read! { read4(T1, T2, T3, T4) }
        fn_read! { read5(T1, T2, T3, T4, T5) }
    }
    fn read_next<'a, T: FromStr, I: Iterator<Item = &'a str>>(i: &mut I) -> T {
        i.next().unwrap().parse().ok().unwrap()
    }

    #[derive(Clone, Copy)]
    pub struct ModInt(pub usize);

    use std::fmt;
    impl fmt::Debug for ModInt {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{:?}", self.0)
        }
    }

    const MOD_BASE: usize = 1000000007;
    const MOD_INV_POW: usize = 1000000005;

    impl ModInt {
        pub fn new(n: usize) -> Self {
            ModInt(n % MOD_BASE)
        }
        pub fn pow(self, mut exp: usize) -> Self {
            let mut b = self;
            let mut r = ModInt(1);
            while exp != 0 {
                if exp % 2 == 1 {
                    r *= b;
                }
                exp /= 2;
                b = b * b;
            }
            r
        }
        pub fn inverse_element(self) -> Self {
            self.pow(MOD_INV_POW)
        }
    }

    macro_rules! ModInt_op {
        (($ot:ident, $f:ident), ($ot_a:ident, $f_a:ident), $($rhs:ty, $e:expr,)*) => {
            $(
            impl $ot<$rhs> for ModInt {
                type Output = Self;
                fn $f(self, rhs: $rhs) -> Self {
                    Self::new(($e)(self, rhs))
                }
            }
            impl $ot_a<$rhs> for ModInt {
                fn $f_a(&mut self, rhs: $rhs) {
                    *self = Self::new(($e)(*self, rhs))
                }
            }
            )*
        }
    }

    ModInt_op!(
        (Add, add),
        (AddAssign, add_assign),
        ModInt,
        |l: ModInt, r: ModInt| l.0 + r.0,
        usize,
        |l: ModInt, r: usize| l.0 + r,
    );

    ModInt_op!(
        (Mul, mul),
        (MulAssign, mul_assign),
        ModInt,
        |l: ModInt, r: ModInt| l.0 * r.0,
        usize,
        |l: ModInt, r: usize| l.0 * r,
    );

    ModInt_op!(
        (Sub, sub),
        (SubAssign, sub_assign),
        ModInt,
        |l: ModInt, r: ModInt| MOD_BASE + l.0 - r.0,
        usize,
        |l: ModInt, r: usize| MOD_BASE + l.0 - r,
    );

    impl Div for ModInt {
        type Output = Self;
        fn div(self, rhs: Self) -> Self {
            self * rhs.inverse_element()
        }
    }
    impl DivAssign for ModInt {
        fn div_assign(&mut self, rhs: Self) {
            *self *= rhs.inverse_element();
        }
    }

    impl Div<usize> for ModInt {
        type Output = Self;
        fn div(self, rhs: usize) -> Self {
            self / ModInt::new(rhs)
        }
    }
    impl DivAssign<usize> for ModInt {
        fn div_assign(&mut self, rhs: usize) {
            *self /= ModInt::new(rhs)
        }
    }

}