[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;
}
posted @ 2018-12-28 16:44  QvvQ  阅读(146)  评论(0编辑  收藏  举报