luogu2568 GCD 题解

\(p\) 为质数且 \(p \le n\)

显然的,若 \(\gcd(x,y)=1\),则 \(\gcd(x \times p,y \times p)=p\)

问题转化为求互质的数对 \((x,y)\) 的个数。

这时候就要用上欧拉函数了!

由于欧拉函数是与一个数互质,那么用前缀和。

由于 \((x,y)\)\((y,x)\) 算两种,所以计数时要乘 \(2\)

\(m\)\(n\) 的约数个数,\(p_i\)\(n\) 的第 \(i\) 个约数。 则答案为

\[ \sum_{i=1}^m{2 \times \varphi \Big(\frac{n}{p_i} \Big)-\varphi(1)} \]

\[ 2 \times \sum_{i=1}^m{\varphi \Big(\frac{n}{p_i} \Big)-1} \]

\[ 2 \times \Bigg(\sum_{i=1}^m{\varphi \Big(\frac{n}{p_i}\Big)} \Bigg) - m \]

实现的时候用欧拉筛。

#include<cstdio>
#include<iostream>
using namespace std;
#define ll long long
const int N=1e7+6;
ll n, m, ans, v[N], p[N], phi[N];
int main() {
    int i, j;
    scanf("%lld",&n);
    phi[1]=1;
    for(i=2;i<=n;++i) {
        if(!v[i]) v[i]=i, p[++m]=i, phi[i]=i-1;
        for(j=1;j<=m;++j) {
            if(p[j]>v[i]||p[j]*i>n) break ;
            v[p[j]*i]=p[j];
            phi[p[j]*i]=phi[i]*(i%p[j]?p[j]-1:p[j]);
        }
        phi[i]+=phi[i-1];
    }
    for(i=1;i<=m;++i) ans+=phi[n/p[i]];
    printf("%lld\n",(ans<<1)-m);
}

luogu2568 GCD 题解
https://yozora0908.github.io/2021/lg2568-solution/
作者
yozora0908
发布于
2021年8月25日
许可协议