- 约数个数和
设 d(x) 为 x 的约数个数,给定 N,M,求
∑i=1N∑j=1Md(ij)
输入格式
输入多组测试数据。
第一行,一个整数 T,表示测试数据的组数。
接下来的 T 行,每行两个整数 N、M。
输出格式
T 行,每行一个整数,表示你所求的答案。
数据范围
1≤N,M,T≤50000
输入样例:
2
7 4
5 6
输出样例:
110
121
#include <bits/stdc++.h>
using namespace std;
const int N = 50010;
typedef long long LL;
int mu[N], prime[N], cnt = 0;
int sum[N], h[N], n, m, k, t;
bool vis[N];
int g(int k, int x) { return k / (k / x); }
void init() {
mu[1] = 1;
for (int i = 2; i < N; i++) {
if (vis[i] == 0) {
prime[cnt++] = i;
mu[i] = -1;
}
for (int j = 0; i * prime[j] < N; j++) {
vis[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
mu[i * prime[j]] = -mu[i];
}
}
for (int i = 1; i < N; i++) {
sum[i] = sum[i - 1] + mu[i];
}
for (int i = 1; i < N; i++) {
for (int l = 1, r; l <= i; l = r + 1) {
r = min(i, g(i, l));
h[i] += (r - l + 1) * (i / l);
}
}
}
int main() {
init();
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
k = min(n, m);
LL ans = 0;
for (int l = 1, r; l <= k; l = r + 1) {
r = min(k, min(g(n, l), g(m, l)));
ans += (LL)(sum[r] - sum[l - 1]) * h[n / l] * h[m / l];
}
printf("%lld\n", ans);
}
}