bitset<2003> v; // 此处作用等价于 bool v[2003]; int N, M, p[305], mu[2003]; ll ans, tot;
inlinevoidsieve(int N){ int m = 0; mu[1] = 1; for(int i = 2; i <= N; ++i) { if(!v[i]) p[++m] = i, mu[i] = -1; for(int j = 1, x; j <= m && i * p[j] <= N; ++j) { x = i * p[j]; v.set(x); // v[x] = 1; if(i % p[j] == 0) break; // 此时 mu[x] = 0; mu[x] = -mu[i]; } mu[i] += mu[i - 1]; // 顺便求出前缀和 } }
intmain(){ cout << fixed << setprecision(7); // 规定输出小数位数 sieve(2000); // min(maxa, maxb) = 2000 while(cin >> N >> M) { if(!N) return0; ans = 0; // 多测不清空,爆零两行泪 if(N > M) swap(N, M); for(int i = 1, j, n, m; i <= N; i = j + 1) { n = N / i, m = M / i; // 可有可无的小常数优化 j = min(N / n, M / m); ans += (ll)(mu[j] - mu[i - 1]) * n * m; } ans = ans * 4 + 4; tot = (ll)(N * 2 + 1) * (M * 2 + 1) - 1; cout << (double)ans / tot << '\n'; } }