#include using namespace std; typedef long long LL; const int N = 1e5 + 10; // 性能非常棒,但是没看懂,等功能加深后再回来看看。 // 据说这道题,还可以用莫比乌斯反演来做,以后再 // 筛法求欧拉函数 int primes[N]; //保存的是每一个质数 int cnt; // cnt代表质数下标,就是到第几个了 int phi[N]; //欧拉函数值,一般叫Φ,函数名不能是希腊字母,所以转为phi bool st[N]; //代表是不是已经被筛掉了 LL res; //结果 void get_eulers(int n) { // 1的欧拉函数值 phi[1] = 1; //如果当前i没有被筛过,说明当前i是一个质数 for (int i = 2; i <= n; i++) { if (!st[i]) { //增加一个质数 primes[cnt++] = i; phi[i] = i - 1; } for (int j = 0; primes[j] <= n / i; j++) { int t = primes[j] * i; st[t] = true; if (i % primes[j] == 0) { phi[t] = phi[i] * primes[j]; break; } else phi[t] = phi[i] * (primes[j] - 1); } } } int n, m; int num, p[10], sum, i; void dfs(int pos, int lcm, int id) { if (id == 0) { if (i & 1) num += (m / lcm); else num -= (m / lcm); return; } if (pos > sum) return; if (lcm * p[pos] <= m) dfs(pos + 1, lcm * p[pos], id - 1); dfs(pos + 1, lcm, id); return; } int solve(int k) { sum = 0; //下面是分解质数 for (int i = 2; i <= k / i; i++) { if (k % i == 0) { p[++sum] = i; while (k % i == 0) k /= i; } } if (k > 1) p[++sum] = k; for (i = 1; i <= sum; i++) dfs(1, 1, i); return m - num; } int main() { //筛法求欧拉函数 get_eulers(N - 10); int T; scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); // n行m列 if (m > n) swap(n, m); LL res = 1; for (int i = 2; i <= m; i++) res += 2 * phi[i]; //这是啥意思呢? for (int i = m + 1; i <= n; i++) { num = 0; res += solve(i); } printf("%lld\n", res); } return 0; }