[BZOJ2818][P2568]Gcd[欧拉函数]
\(gcd(x,y)=p | p∈P\)
\(gcd(x_1\times p,y_1\times p) = p\)
\(gcd(x_1,y_1)=1\)
每个素数的贡献是对于\([1,\lfloor\frac{n}{prime[i]}\rfloor]\)里的每个数的欧拉函数的前缀和,因为\((x_1,y_1)\)可以交换,就乘上2,重复计算了\((1,1)\),还要减去1
#include <bits/stdc++.h>
using namespace std;
#define read2(a, b) (read(a), read(b))
#define read3(a, b, c) (read(a), read(b), read(c))
const int inf = 0x3f3f3f3f-1;
const int MAXN = 1e7+7;
template<class T> void read(T & x) {
register int c = getchar(), f = 1;x = 0;
while(!isdigit(c)) {if (c == '-') f = -f;c = getchar();}
while(isdigit(c)) x = x * 10 + c - '0', c = getchar();
x *= f;
}
int prime[MAXN], n, tot, phi[MAXN], m;
long long ans, pre[MAXN];
bool notprime[MAXN];
void calcphi() {
phi[1] = 1;
for(int i = 2; i <= n; ++i) {
if (!notprime[i]) prime[++tot] = i, phi[i] = i - 1;
for(int j = 1; j <= tot; ++j) {
if (i * prime[j] > n) break;
notprime[i * prime[j]] = 1;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else phi[i * prime[j]] = phi[i] * phi[prime[j]];
}
}
}
int main(void) {
cin >> n;
calcphi();
for(int i = 1; i <= n; ++i) pre[i] = pre[i-1] + phi[i];
for(int i = 1; i <= tot; ++i)
ans += pre[n / prime[i]] * 2 - 1;
cout << ans;
return 0;
}