bzoj 2818: Gcd
题目链接
题解
对于一个素数p
我们可以求出n中有多少个他的倍数 \(k_xp\)
其中,若两数的系数\(k_x\)互质,那么这两数的gcd为素数p
对于一个素数p也就是求$\lfloor \frac{n}{p} \rfloor $中两两互素数的个数,欧拉函数前缀和就好了
代码
#include<cstdio>
#include<algorithm>
const int maxn = 10000007;
int prime[maxn],num;
bool is_prime[maxn];long long phi[maxn];
void get_phi(int n ) {
is_prime[1] = true;
phi[1] = 1;
for(int i = 2;i <= n;++ i) {
if(!is_prime[i]) prime[++ num] = i,phi[i] = i - 1;
for(int j = 1;j <= num && prime[j] * i <= n;++ j) {
is_prime[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] * (prime[j] - 1) ;
}
}
}
#define LL long long
int main() {
int n;
scanf("%d",&n);
get_phi(n);
LL ans = 0;
int tmp = 0;
for(int i = 1;i <= n;++ i) phi[i] += phi[i - 1];
for(int i = 1;i <= num;++ i) {
ans += 1ll*(phi[n / prime[i]] * 2 - 1);
//if(phi[n / prime[i]]) ans += phi[n / prime[i]] + 1;
}
printf("%lld\n",ans);
return 0;
}