#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define pb push_back
#define mp make_pair
const int MAXN=205;
const ll mod = 1000000007;
const ll inf = 1e18;
typedef pair<int, int> pi;
ll gc(ll a,ll b)
{
    if(b==0) return a;
    return gc(b,a%b);
}
ll power(ll x, ll y, ll p)
{
    ll res = 1;     // Initialize result

    x = x % p; // Update x if it is more than or
                // equal to p

    if (x == 0) return 0; // In case x is divisible by p;

    while (y > 0)
    {
        // If y is odd, multiply x with result
        if (y & 1)
            res = (res*x) % p;

        // y must be even now
        y = y>>1; // y = y/2
        x = (x*x) % p;
    }
    return res;
}

vector<bool>prime(100005,true);
vector<ll>v;
void sieve(ll n)
{
    prime[1]=false;
   for (int p=2; p*p<=n; p++)
    {
        // If prime[p] is not changed, then it is a prime
        if (prime[p] == true)
        {
            // Update all multiples of p greater than or
            // equal to the square of it
            // numbers which are multiple of p and are
            // less than p^2 are already been marked.
            for (int i=p*p; i<=n; i += p)
                prime[i] = false;
        }
    }

    for(int i=2;i<=n;i++)
    {
        if(prime[i]==true)
            v.push_back(i);
    }
}

bool comp(pair<ll,ll> &p1, pair<ll,ll> &p2)
{
    return (p1.second<p2.second);
}
int BIT[1000];
void update(int x, int delta)
{
    int n;
      for(; x <= n; x += x&-x)
        BIT[x] += delta;
}
int query(int x)
{
     int sum = 0;
     for(; x > 0; x -= x&-x)
        sum += BIT[x];
     return sum;
}

vector<vector<ll> >dp(30005,vector<ll>(248,-1));


void lcs()
{
vector<int> d;
int ans, n;
 for (int i = 0; i < n; i++) {
        int x;
        scanf("%d", &x);
        vector<int>::iterator it = upper_bound(d.begin(), d.end(), x);
        if (it == d.end()) d.push_back(x);
        else *it = x;
    }
    printf("LIS = %d", d.size());
}

ll dfs(ll src,ll p, vector<ll> adj[],vector<ll>& sz)
{
    sz[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        ll v=adj[src][i];
        if(v==p) continue;
        sz[src]+=dfs(v, src,adj,sz);
    }
    return sz[src];
}
void dfs2(ll src , ll p, vector<ll> adj[], vector<ll> & dp, vector<ll>& ans, ll m)
{
    ans[src]=dp[src];
    for(int i=0;i<adj[src].size();i++)
    {
        ll v=adj[src][i];
        if(v==p) continue;
        dp[src]/=(dp[v]+1);
        dp[v]=((dp[v]%m)*(dp[src]+1)%m)%m;
        dfs2(v,src,adj,dp,ans,m
             );
        dp[v]/=(dp[src]+1);
        dp[src]=((dp[src]%m)*(dp[v]+1)%m);
    }
    return;
}

inline ll add(ll a,ll b) {return ((a%mod)+(b%mod))%mod;}
inline ll sub(ll a,ll b) {return ((a%mod)-(b%mod)+mod)%mod;}
inline ll mul(ll a,ll b) {return ((a%mod)*(b%mod))%mod;}
ll dfs1(vector<ll> adj[], ll src, ll p,ll col, vector<ll>& dp)
{
    dp[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        ll v=adj[src][i];
        if(v==p) continue;
        ll st=dfs1(adj, v,src, 1,dp);
        if(col==1)
        {
            ll temp=0;
            temp=add(temp,dfs1(adj,v,src,0,dp));
            temp=add(temp,st);
            dp[src]=mul(dp[src],temp);
        }
        else
        {
            dp[src]=mul(dp[src],st);
        }

    }
    return dp[src];
}

ll solution( vector<ll> A, ll k)
{
    // seiz of the vector
    // which does is constant
    ll N = A.size();

    // bases cases
    if (N < k || N < 1 || k < 1)
        return 0;
    if (N == k)
        return 1;

    // Prepare arrays for recursion
    vector<ll> v1(N, 0);
    vector<ll> v2(N, 0);
    vector<ll> v3(N, 0);

    // initiate separately for k = 1
    // intiate the last element
    v2[N - 1] = 1;
    v3[A[N - 1] - 1] = 1;

    // initiate all other elements of k = 1
    for (ll i = N - 2; i >= 0; i--) {

        // initialize the front element
        // to vector v2
        v2[i] = v2[i + 1];

        // if element v[a[i]-1] is 0
        // then increment it in vector v2
        if (v3[A[i] - 1] == 0) {
            v2[i]++;
            v3[A[i] - 1] = 1;
        }
    }

    // iterate for all possible values of K
    for (ll j = 1; j < k; j++) {

        // fill the vectors with 0
        fill(v3.begin(), v3.end(), 0);

        // fill(v1.begin(), v1.end(), 0)
        // the last must be 0 as from last no unique
        // subarray can be formed
        v1[N - 1] = 0;

        // Iterate for all index from which unique
        // subsequences can be formed
        for (ll i = N - 2; i >= 0; i--) {

            // add the number of subsequence formed
            // from the next index
            v1[i] = v1[i + 1];

            // start with combinations on the
            // next index
            v1[i] = v1[i] + v2[i + 1];

            // Remove the elements which have
            // already been counted
            v1[i] = v1[i] - v3[A[i] - 1];

            // Update the number used
            v3[A[i] - 1] = v2[i + 1];
        }

        // prepare the next iteration
        // by filling v2 in v1
        v2 = v1;
    }

    // last answer is stored in v1
    return v1[0];
}
ll recur(ll idx,ll sum, vector<pair<ll,ll> >& v, vector<ll>& b, vector<ll>& pre, vector<ll>& dp)
{
    if(idx==b.size()) return 0;
    if(dp[idx]!=-1) return dp[idx];
    ll temp=INT_MAX;
    temp=min(temp,recur(idx+1,sum,v,b,pre,dp) + b[idx]);
    for(int i=0;i<v.size();i++)
    {
        ll x=v[i].first;
        ll y=v[i].second;
        if(idx+x-1>=b.size()) continue;
        ll calc= pre[idx+x-1]-pre[idx+y-1];
        temp=min(temp, recur(idx+x, sum,v,b,pre,dp)+ calc);
    }
    dp[idx]=temp;
    return temp;
}
set<pair<ll,ll> >temp;

void dfs(ll src, vector<ll>& p, vector<ll> adj[],vector<bool>& vis, vector<bool>& v)
{
    vector<ll>:: iterator it;
    vis[src]=true;
    for( it=adj[src].begin();it!=adj[src].end();it++)
    {
        if((*it)==p[src]) continue;

        if(!vis[*it])
        {
            p[*it]=src;
            dfs((*it), p,adj, vis,v);
        }
        else
        {
        if(v[*it]==true) continue;
        else
        {
            ll c=(*it);
            ll d=src;
            temp.insert(mp(c,d));
            v[c]=true;
            v[d]=true;
            ll coun=1;
            while(d!=c)
            {
                temp.insert(mp(d,p[d]));
                coun++;
                v[p[d]]=true;
                d=p[d];
            }

        }
        }
    }
}
ll recur(ll idx,ll k, ll n)
{
    if(idx==n) return 1;
    if(idx>n) return 0;
    ll temp=0;
    temp+=recur(idx+1,k,n);
    temp+=(idx+k, k,n);
    return temp;
}
ll find(ll u, vector<ll>& parent)
{
    if(u==parent[u]) return u;
    else return parent[u]=find(parent[u],parent);
}
 void unio(ll u, ll v, vector<ll>& parent, vector<ll>& ran, map<ll,ll>& m1)
{
    u=find(u,parent);
    v=find(v,parent);
    if(u==v) return;
    if(ran[u]>=ran[v])
    {
        parent[v]=u;
        ran[u]+=v;
        m1[u]+=m1[v];
    }
    else{
        parent[u]=v;
        ran[v]+=u;
        m1[v]+=m1[u];
    }
}
ll dfs(ll src, ll p, vector<ll>& a, vector<pair<ll,ll> > adj[], vector<ll>& dp)
{
    ll can1=0;
    ll can2=0;
    vector<pair<ll,ll> >:: iterator it;
    for(it=adj[src].begin();it!=adj[src].end();it++)
    {
        if(((*it).first==p)) continue;
        ll st=max(0LL,dfs((*it).first,src,a,adj,dp)- (*it).second);
        if(st>can1)
        {
            can2=can1;
            can1=st;
        }
        else if(st>can2)
        {
            can2=st;
        }
    }
    dp[src]=a[src]+ can1+can2;
    return (max(can1,can2)+ a[src]);
}
map<ll,ll>ma;
map<pair<ll,ll>,ll>m2;
void dfs(ll src,vector<pair<ll,ll> > adj[],vector<bool>& vis,ll coun, vector<ll> & asign)
{
    vis[src]=true;
    asign[src]=coun;
    for(int i=0;i<adj[src].size();i++)
    {
        ll nod=adj[src][i].first;
        ll w=adj[src][i].second;
        if(vis[nod] || w!=0) continue;

        dfs(nod,adj,vis,coun,asign);
    }
}
 vector<ll>adj[100005];
 vector<ll>d(100005);
ll dfs(ll src, ll p, vector<ll>& sub)
{
    sub[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        if (adj[src][i]==p) continue;
        dfs(adj[src][i], src, sub);
         sub[src]+=(sub[adj[src][i]]);
    }
    return sub[src];
}
struct comp1{
    bool operator ()(pair<ll,ll>& temp1, pair<ll,ll>& temp2)
{
    return (d[temp1.second]< d[temp2.second] || (d[temp1.second]==d[temp2.second] && adj[temp1.second].size()>adj[temp2.second].size()));
}
};
bool comp2(pair<ll,ll>& temp1, pair<ll,ll>& temp2)
{
    return temp1.second<temp2.second;
}



bool belong(ll i, ll j, ll l, ll u, ll r, ll d)
{
    if(i>r || i<l || j>d || j<u)
    return true;
    return false;
}

int main() {
ll n,m;
cin>>n>>m;
ll temp=m;
vector<pair<ll,ll> >p;
for(ll i=2;i*i<=m;i++)
{
    ll coun=0;
    while(temp%i==0)
    {
        temp/=i;
        coun++;
    }
  if(coun!=0)
  {
      p.pb(mp(i,coun));
  }

}
if(temp!=1)
{
    p.pb(mp(temp,1));
}
ll ans=1;
vector<ll>fac(1000005);
vector<ll>inv(1000005);
fac[1]=1;
fac[0]=1;
for(ll i=2;i<fac.size();i++)
{
    fac[i]=mul(i,fac[i-1]);
}
for(ll i=0;i<fac.size();i++)
{
    inv[i]=power(fac[i],mod-2,mod);
}

for(ll i=0;i<p.size();i++)
{
    pair<ll,ll>temp=p[i];
    ll coun=temp.second;
    ll sum=coun+n-1;
    ans=mul(ans,fac[sum]);
    ans=mul(ans,inv[coun]);
    ans=mul(ans,inv[sum-coun]);
}
cout<<ans;
}

Measured memory_bytes: 80384