#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxr = 1e6 + 6, maxn = 1e6 + 6;
const int mod = 1e9 + 7;
bool notPrime[maxn];
int ch[maxr + 50][25];
vector<int> primes;
vector<int> l;
int sum(int r, int a, int b) {
return (ch[r + b][b] - (a == 0 ? 0 : ch[r + a - 1][a - 1]) + mod);
}
int r, n;
int comp(int i, ll coeff, int dist) {
if(i == l.size()) {
return (coeff*(1 << dist)) % mod;
}
else {
return (comp(i + 1, (coeff*sum(r - 1, 0, l[i] - 1)) % mod, dist + 1)
+ comp(i + 1, (coeff*sum(r - 1, l[i], l[i])) % mod, dist)) % mod;
}
}
int main() {
ch[0][0] = 1;
for(int i = 1; i <= 1e6 + 22; i++) {
ch[i][0] = 1;
for(int j = 1; j <= 20; j++) {
ch[i][j] = (ch[i - 1][j - 1] + ch[i - 1][j]) % mod;
}
}
for(int i = 1; i <= 1e6 + 22; i++) {
for(int j = 1; j <= 20; j++) {
ch[i][j] = (ch[i][j] + ch[i - 1][j - 1]) % mod;
}
}
for(int i = 2; i <= 1e3; i++) {
if(!notPrime[i]) {
primes.push_back(i);
for(int j = i + i; j <= 1e3; j += i) {
notPrime[j] = true;
}
}
}
int q;
scanf("%d", &q);
while(q--) {
l.clear();
scanf("%d%d", &r, &n);
for(int p : primes) {
if(n == 1 || p*p > n) {
break;
}
else if(n % p == 0) {
l.push_back(1);
n /= p;
while(n % p == 0) {
l.back()++;
n /= p;
}
}
}
if(n != 1) {
l.push_back(1);
}
printf("%d\n", (r == 0 ? (1 << l.size()) : comp(0, 1, 0)));
}
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CnR5cGVkZWYgbG9uZyBsb25nIGxsOwoKY29uc3QgaW50IG1heHIgPSAxZTYgKyA2LCBtYXhuID0gMWU2ICsgNjsKY29uc3QgaW50IG1vZCA9IDFlOSArIDc7Cgpib29sIG5vdFByaW1lW21heG5dOwppbnQgY2hbbWF4ciArIDUwXVsyNV07CnZlY3RvcjxpbnQ+IHByaW1lczsKdmVjdG9yPGludD4gbDsKCmludCBzdW0oaW50IHIsIGludCBhLCBpbnQgYikgewoJcmV0dXJuIChjaFtyICsgYl1bYl0gLSAoYSA9PSAwID8gMCA6IGNoW3IgKyBhIC0gMV1bYSAtIDFdKSArIG1vZCk7Cn0KCmludCByLCBuOwppbnQgY29tcChpbnQgaSwgbGwgY29lZmYsIGludCBkaXN0KSB7CglpZihpID09IGwuc2l6ZSgpKSB7CgkJcmV0dXJuIChjb2VmZiooMSA8PCBkaXN0KSkgJSBtb2Q7Cgl9CgllbHNlIHsKCQlyZXR1cm4gKGNvbXAoaSArIDEsIChjb2VmZipzdW0ociAtIDEsIDAsIGxbaV0gLSAxKSkgJSBtb2QsIGRpc3QgKyAxKQoJCQkJKyBjb21wKGkgKyAxLCAoY29lZmYqc3VtKHIgLSAxLCBsW2ldLCBsW2ldKSkgJSBtb2QsIGRpc3QpKSAlIG1vZDsKCX0KfQoKaW50IG1haW4oKSB7CgljaFswXVswXSA9IDE7Cglmb3IoaW50IGkgPSAxOyBpIDw9IDFlNiArIDIyOyBpKyspIHsKCQljaFtpXVswXSA9IDE7CgkJZm9yKGludCBqID0gMTsgaiA8PSAyMDsgaisrKSB7CgkJCWNoW2ldW2pdID0gKGNoW2kgLSAxXVtqIC0gMV0gKyBjaFtpIC0gMV1bal0pICUgbW9kOwoJCX0KCX0KCWZvcihpbnQgaSA9IDE7IGkgPD0gMWU2ICsgMjI7IGkrKykgewoJCWZvcihpbnQgaiA9IDE7IGogPD0gMjA7IGorKykgewoJCQljaFtpXVtqXSA9IChjaFtpXVtqXSArIGNoW2kgLSAxXVtqIC0gMV0pICUgbW9kOwoJCX0KCX0KCglmb3IoaW50IGkgPSAyOyBpIDw9IDFlMzsgaSsrKSB7CgkJaWYoIW5vdFByaW1lW2ldKSB7CgkJCXByaW1lcy5wdXNoX2JhY2soaSk7CgkJCWZvcihpbnQgaiA9IGkgKyBpOyBqIDw9IDFlMzsgaiArPSBpKSB7CgkJCQlub3RQcmltZVtqXSA9IHRydWU7CgkJCX0KCQl9Cgl9CgoJaW50IHE7CglzY2FuZigiJWQiLCAmcSk7Cgl3aGlsZShxLS0pIHsKCQlsLmNsZWFyKCk7CgkJc2NhbmYoIiVkJWQiLCAmciwgJm4pOwoJCWZvcihpbnQgcCA6IHByaW1lcykgewoJCQlpZihuID09IDEgfHwgcCpwID4gbikgewoJCQkJYnJlYWs7CgkJCX0KCQkJZWxzZSBpZihuICUgcCA9PSAwKSB7CgkJCQlsLnB1c2hfYmFjaygxKTsKCQkJCW4gLz0gcDsKCQkJCXdoaWxlKG4gJSBwID09IDApIHsKCQkJCQlsLmJhY2soKSsrOwoJCQkJCW4gLz0gcDsKCQkJCX0KCQkJfQoJCX0KCQlpZihuICE9IDEpIHsKCQkJbC5wdXNoX2JhY2soMSk7CgkJfQogICAgICAgIHByaW50ZigiJWRcbiIsIChyID09IDAgPyAoMSA8PCBsLnNpemUoKSkgOiBjb21wKDAsIDEsIDApKSk7Cgl9CglyZXR1cm4gMDsKfQ==