#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <iomanip>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <queue>
#include <stack>
#include <functional>
#include <algorithm>
#include <climits>
#include <sstream>
#include <complex>

using namespace std;

using ii = pair<int, int>;
using vi = vector<int>;
using vii = vector<ii>;
using vvi = vector<vi>;
using iii = pair<int, ii>;
using viii = vector<iii>;

using ll = long long int;
using vc = vector<char>;
using vb = vector<bool>;
using ib = pair<int, bool>;
using vib = vector<ib>;

#define MOD 1000 * 1000 * 1000 + 7
#define INF 1000 * 1000 * 1000
#define EMPTY -10
#define mp(a, b) make_pair(a,b)

//Criba de Eratostenes
vector<bool> marcaje(50000, true); //Colocar n = sqrt(limite del problema)
vector<int> primes;

void sieve() { //Ejecutar al principio del programa
	marcaje[0] = marcaje[1] = 0;
	for (int i = 2; i < marcaje.size(); i++)
		if (marcaje[i]) {
			for (int j = i * i; j < marcaje.size(); j += i) marcaje[j] = 0;
			primes.push_back(i);
		}
}

vector<int> primeFactors(int N) { //int numPF(int N)
	vector<int> factors; //int ans = 0;
	int PF_idx = 0, PF = primes[PF_idx];
	while (PF_idx < primes.size() && PF * PF <= N) {
		while (N % PF == 0) {
			N /= PF;
			factors.push_back(PF); //++ans;
		}
		PF = primes[++PF_idx];
	}
	if (N != 1) factors.push_back(N); //++ans;   // N is prime 
	return factors; // ans;
}

int solve(int n, int factoresQueAunQuedan, map<int, int> & bij, vvi & marcaje) {
	if (factoresQueAunQuedan == 1) return 1;
	else if (n <= 0) return 0;
	else if (n == 1) return 1;
	else if (marcaje[n][bij[factoresQueAunQuedan]] != EMPTY) 
		return marcaje[n][bij[factoresQueAunQuedan]];
	else {
		int sol = 0;

		for (auto it = bij.begin(); it != bij.end(); ++it) {
			if (it->first > factoresQueAunQuedan) break;
			else if (factoresQueAunQuedan % it->first == 0) {
				if (n % 2 == 0) {
					ll solAux = solve(n / 2, (factoresQueAunQuedan / it->first), bij, marcaje);
					ll solAux2 = solve(n / 2, it->first, bij, marcaje);

					ll solParcial = solAux * solAux2;
					sol = ((sol + solParcial) % 1000000007);
				}
				else {
					ll solAux = solve(n / 2, (factoresQueAunQuedan / it->first), bij, marcaje);
					ll solAux2 = solve((n / 2) + 1, it->first, bij, marcaje);
					
					ll solParcial = solAux * solAux2;
					sol = ((sol + solParcial) % 1000000007);
				}
			}
		}
		marcaje[n][bij[factoresQueAunQuedan]] = sol;
		return sol;
	}
}

bool resuelveCaso() {
	int n;
	cin >> n;
	int m;
	if (!cin) return false;
	cin >> m;

	if (m == 1) {
		cout << 1 << '\n';
	}
	else {
		vi fact = primeFactors(m);

		set<int> knAct, knSig, knAux;
		int res;
		knAct.insert(1);
		knAct.insert(fact[0]);
		for (int i = 1; i < fact.size(); ++i) {
			for (auto it = knAct.begin(); it != knAct.end(); ++it) {
				knSig.insert(*it);
				knSig.insert((*it * fact[i]));
			}
			knAct = knSig;
			knSig = knAux;
		}

		map<int, int> biy;
		int cont = 0;
		for (auto it = knAct.begin(); it != knAct.end(); ++it) {
			biy.insert(mp(*it, cont));
			++cont;
		}

		vvi marcaje(n + 1, vi(cont + 1, EMPTY));

		int solucion = solve(n, m, biy, marcaje);

		cout << solucion << '\n';
	}
	return true;
}

int main() {
	sieve();
	while (resuelveCaso()) {}
	return 0;
}

Measured memory_bytes: 379264