` `#include <cstdio>
#include <cstring>
typedef unsigned long long u64;
const int MAX_SQRT_N = 1e5;
struct euler_sieve {
static const int MAX_N = MAX_SQRT_N;
bool f[MAX_N + 10];
int p[MAX_N + 10];
int p_n;
inline void operator()(int n) {
memset(f, 0, sizeof f);
p_n = 0;
for (int i = 2; i <= n; ++i) {
if (!f[i]) {
p[++p_n] = i;
}
for (int j = 1; p[j] * i <= n; ++j) {
f[p[j] * i] = true;
if (i % p[j] == 0) break;
}
}
}
} es;
struct Min_25_sieve {
u64 n;
u64 b[2 * MAX_SQRT_N + 10]; // 所有可能的 n / i 值，值是从大到小的（废话）
int b_n, sqrt_n;
inline int locate(u64 i) { return i < sqrt_n ? b_n - i + 1 : n / i; } // 查找 b[j] == i 的位置 j
int d0[2 * MAX_SQRT_N + 10]; // 存储 h 函数的值，数组命名个人癖好而已。 The value of the H function is only O (\sqrt n). The location at I is not h (I), but h (b[i])
inline void pre_calc () {/ / compute h function
for (int = 1; I) = = 1; * = (* 1); / / ((0)). 这里以及下面的 1 * 代表的就是 i^k （本题中 k = 0（不是输入的那个 k 啊））
for (int j = 1; (u64)es.p[j] * es.p[j] <= n; ++j) { // 枚举质数
for (int i = 1; (u64)es.p[j] * es.p[j] <= b[i]; ++i) { // 枚举了有用的，即 b[i]
d0[i] = d0[i] - 1 * (d0[locate(b[i] / es.p[j])] - d0[locate(es.p[j] - 1)]); // 一定有 p[j] - 1 < \sqrt n ，所以一定可以找到一个合法的位置（不会落在一个段内） // 由于 b[i] 的值是从大道小的，所以求值顺序是没有问题的，不用开另外一个缓存数组
}
}
}
u64 f_a0_k;
inline u64 f_a0(int e) { return e * f_a0_k + 1; }
inline u64 f(int p, int e) { return f_a0(e); }
u64 calc(u64 n, int m) { // 计算 g 函数
u64 rst = f_a0(1) * (d0[locate(n)] - d0[locate(es.p[m])]);
for (int j = m + 1; (u64)es.p[j] * es.p[j] <= n; ++j) {
u64 pe = es.p[j];
for (int e = 1; (u64)pe * es.p[j] <= n; ++e, pe *= es .p[j]) {
rst += f(es.p[j], e) * calc(n / pe, j) + f(es.p[j], e + 1);
}
}
return rst;
}
inline u64 operator()(u64 n_, u64 f_a0_k_) {
n = n_;
f_a0_k = f_a0_k_;
// 分块
sqrt_n = 0; while ((u64)sqrt_n * sqrt_n < n) ++sqrt_n;
b_n = 0; for (u64 i = 1; i <= n; i = n / (n / i) + 1) b[++b_n] = n / i;
// 处理辅助求和函数
pre_calc();
// 求和
es.p[0] = 0, d0[b_n + 1] = 0;
return calc(n, 0) + 1; // + 1 是那个甩单的 1
}
} mns;
int main() {
// freopen("in.in", "r", stdin);
int tc; scanf("%d", &tc);
// int tc = 1;
es(MAX_SQRT_N + 5); // 筛出质数
while (tc--) {
u64 n, f_a0_k; scanf("%llu%llu", &n, &f_a0_k);
printf("%llu\n", mns(n, f_a0_k));
}
return 0;
}