Category talk
For a number satisfying the requirements of (x, y), there are two cases:
A: x, y, there is a prime number p, p is a multiple of another number, this time gcd (x, y) p apparently, to meet the requirements
B: x = p · k1, y = p · k2, p is a prime number, and k1, k2 coprime, gcd (x, y) is also a prime number p
Calculation program
First with a linear prime sieve and recursive functions Euler the preprocessing 1 - Euler function prime number n and the number of each
In the case of
A: Each enumerator prime, attention (x, y) and (y, x) is different, so is multiplied by 2, but x, y can only be considered a kind of the same, so by subtracting 2 1
B: Enumeration 1 - n for each number i, x = p · k1, y = p · k2 (p is a prime number), where k1 is the number of i are satisfied :( p · k1 <= n and p <= the number of the prime number p i,) * (before i and i the number of mutually prime numbers (the Euler function)), note also multiplied by 2
Code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e7 + 5;
int n, tot, k[N], p[N], a[N], s[N];
long long res;
void Pre_work () {
for (int i = 2; i <= n; ++i) {
if (!k[i]) p[++tot] = i, a[i] = i - 1; //如果是质数,与 i 互质的数的个数为 i-1
for (int j = 1; j <= tot, p[j] * i <= n; ++j) {
k[p[j] * i] = 1, a[p[j] * i] = a[i] * (p[j] - (i % p[j] != 0)); //套用欧拉函数递推式
if (i % p[j] == 0) break;
}
}
for (int i = 2; i <= n; ++i) s[i] = s[i - 1] + (k[i] == 0); //预处理质数个数的前缀和
}
int main() {
scanf ("%d", &n);
Pre_work ();
for (int i = 2; i <= n; ++i) res += s[n / i] * (a[i] - 1) << 1; //情况 B
for (int i = 1; i <= tot and p[i] <= n; ++i) res += ((n / p[i]) << 1) - 1; //情况 A
printf ("%lld\n", res);
return 0;
}