[BZOJ2818][P2568]Gcd[尤拉函式]
阿新 • • 發佈:2018-12-28
\[gcd(x,y)=p | p∈P\]
\[\iff\] \[gcd(x_1\times p,y_1\times p) = p\]
\[\iff\] \[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; }