#include <bits/stdc++.h>
using namespace std;
const int inf = 2000000000;
static inline int Rint() {
  struct X {
    int dig[256];
    X() {
      for (int i = '0'; i <= '9'; ++i) dig[i] = 1;
      dig['-'] = 1;
    }
  };
  static X fuck;
  int s = 1, v = 0, c;
  for (; !fuck.dig[c = getchar()];)
    ;
  if (c == '-')
    s = 0;
  else if (fuck.dig[c])
    v = c ^ 48;
  for (; fuck.dig[c = getchar()]; v = v * 10 + (c ^ 48))
    ;
  return s ? v : -v;
}
template <typename T>
static inline void cmax(T& a, const T& b) {
  if (b > a) a = b;
}
template <typename T>
static inline void cmin(T& a, const T& b) {
  if (b < a) a = b;
}
template <long long P>
struct moder {
  static long long inv(long long x) {
    long long result = 1;
    int n = P - 2;
    x %= P;
    for (; n; n >>= 1, x = x * x % P)
      if (n & 1) result = result * x % P;
    return result;
  }
  static long long* fac;
  static void init_fac() {
    fac = new long long[1048576];
    fac[0] = 1;
    for (int i = 1; i < 1048576; ++i) fac[i] = fac[i - 1] * i % P;
  }
  static void destroy_fac() { delete[] fac; }
  static long long s(int x) { return x & 1 ? -1 : 1; }
  static long long comb(long long m, long long n) {
    if (n > m || n < 0) return 0;
    long long pp = 0;
    long long dist = m - n;
    for (long long x = P; x <= m; x *= P) pp += m / x - n / x - dist / x;
    if (pp) return 0;
    long long l = 1, r = 1;
    for (long long x = m; x; x /= P) l = l * s(x / P) * fac[x % P] % P;
    for (long long x = n; x; x /= P) r = r * s(x / P) * fac[x % P] % P;
    for (long long x = dist; x; x /= P) r = r * s(x / P) * fac[x % P] % P;
    l = (l + P) % P;
    r = (r + P) % P;
    long long t = (inv(r) * l % P + P) % P;
    return t;
  }
};
const long long p = 1000000007;
const long long mod = p;
template <long long P>
long long* moder<P>::fac;
moder<p> md;
const int maxp = 200005;
static int plist[maxp / 3], pmask[maxp + 1];
int pcnt;
void init_primes() {
  for (int i = 1; i <= maxp; ++i) pmask[i] = i;
  for (int i = 2; i <= maxp; ++i) {
    if (pmask[i] == i) {
      plist[pcnt++] = i;
    }
    for (int j = 0; j < pcnt; ++j) {
      const long long t = (long long)plist[j] * i;
      if (t > maxp) break;
      pmask[t] = plist[j];
      if (i % plist[j] == 0) {
        break;
      }
    }
  }
}
static long long pv[1024];
int pc[1024];
static long long factors[655360];
static int factor_cnt;
void get_factors(int limit, long long value) {
  factors[factor_cnt++] = value;
  for (int i = 0; i < limit; ++i) {
    long long tvalue = value;
    const int p = pv[i];
    for (int j = 1; j <= pc[i]; ++j) {
      tvalue *= p;
      get_factors(i, tvalue);
    }
  }
}
int factorize(long long n) {
  int top = 0;
  if (n <= maxp) {
    while (n != 1) {
      int now = pmask[n];
      int c = 0;
      while (n % now == 0) n /= now, ++c;
      if (c) pv[top] = now, pc[top++] = c;
    }
  } else {
    for (int i = 0; i < pcnt; ++i) {
      const long long p = plist[i];
      const long long test = p * p;
      if (p > n) break;
      int c = 0;
      while (n % p == 0) n /= p, ++c;
      if (c) pv[top] = p, pc[top++] = c;
    }
    if (n != 1) pv[top] = n, pc[top++] = 1;
  }
  return top;
}
static inline long long add(long long a, long long b) {
  a += b;
  if (a >= mod) a -= mod;
  return a;
}
static inline long long sub(long long a, long long b) {
  a -= b;
  if (a < 0) a += mod;
  return a;
}
long long dp[655360];
vector<int> adj[1005];
struct Query {
  int n, f;
  int id, ans;
};
int cmp_n(const Query& a, const Query& b) {
  if (a.n != b.n) return a.n < b.n;
  return a.f < b.f;
}
int cmp_id(const Query& a, const Query& b) { return a.id < b.id; }
Query data[100005];
int main() {
  md.init_fac();
  init_primes();
  int q = Rint();
  for (int i = (0); i < (q); ++i)
    data[i].n = Rint(), data[i].f = Rint(), data[i].id = i;
  sort(data, data + q, cmp_n);
  for (int x = 0; x < q; ++x) {
    const int n = data[x].n, f = data[x].f;
    if (n == 1) {
      data[x].ans = f == 1 ? 1 : 0;
      continue;
    }
    if (f > n) {
      data[x].ans = 0;
      continue;
    }
    if (f == 1) {
      data[x].ans = 0;
      continue;
    }
    if (f == n) {
      data[x].ans = 1;
      continue;
    }
    factor_cnt = 0;
    get_factors(factorize(n), 1);
    sort(factors, factors + factor_cnt);
    for (int i = 0; i < factor_cnt; ++i) adj[i].clear();
    int t = 0;
    for (int i = 0; i < factor_cnt; ++i)
      for (int j = i + 1; j < factor_cnt; ++j)
        if (factors[j] % factors[i] == 0) adj[i].push_back(j), ++t;
    int j = x;
    while (j < q && data[j].n == data[x].n) {
      const int f = data[j].f;
      if (j > x && f == data[j - 1].f) {
        data[j].ans = data[j - 1].ans;
        ++j;
        continue;
      }
      for (int i = 0; i < factor_cnt; ++i) dp[i] = 0;
      for (int i = 0; i < factor_cnt; ++i) {
        const long long val = factors[i];
        if (val < f) {
          dp[i] = 0;
          continue;
        }
        const long long t = md.comb(f + val - f - 1, val - f);
        dp[i] = add(dp[i], t);
        for (int j = 0; j < adj[i].size(); ++j)
          dp[adj[i][j]] = sub(dp[adj[i][j]], dp[i]);
      }
      data[j].ans = dp[factor_cnt - 1];
      ++j;
    }
    x = j - 1;
  }
  sort(data, data + q, cmp_id);
  for (int i = 0; i < q; ++i) printf("%d\n", data[i].ans);
  return 0;
}
