AcWing 220. 最大公约数 (欧拉函数)

AcWing 220. 最大公约数

题意

给一个整数 n ( 1 ≤ n ≤ 1 0 7 ) n(1\le n \le 10^7) n(1n107) ,问 1 ≤ x , y ≤ n 1\le x,y\le n 1x,yn g c d ( x , y ) gcd(x,y) gcd(x,y) 是素数的数有多少对。

解法

a n s = ∑ p ∑ x = 1 n ∑ y = 1 n [ g c d ( x , y ) = = p ] = ∑ p ∑ x = 1 n ∑ y = 1 n [ g c d ( x / p , y / p ) = = 1 ] = ∑ p ∑ x = 1 n / p ∑ y = 1 n / p [ g c d ( x , y ) = = 1 ] = ∑ p ( ∑ x = 1 n / p 2 ( ∑ y = 1 x [ g c d ( x , y ) = = 1 ] ) − 1 ) = ∑ p ( ∑ x = 1 n / p 2 φ ( x ) − 1 ) \begin{aligned} ans&=\sum_{p}\sum_{x=1}^{n}\sum_{y=1}^{n}[gcd(x,y)==p]\\ &=\sum_{p}\sum_{x=1}^{n}\sum_{y=1}^{n}[gcd(x/p,y/p)==1]\\ &=\sum_{p}\sum_{x=1}^{n/p}\sum_{y=1}^{n/p}[gcd(x,y)==1]\\ &=\sum_{p}(\sum_{x=1}^{n/p}2(\sum_{y=1}^{x}[gcd(x,y)==1])-1)\\ &=\sum_{p}(\sum_{x=1}^{n/p}2\varphi (x)-1) \end{aligned} ans=px=1ny=1n[gcd(x,y)==p]=px=1ny=1n[gcd(x/p,y/p)==1]=px=1n/py=1n/p[gcd(x,y)==1]=p(x=1n/p2(y=1x[gcd(x,y)==1])1)=p(x=1n/p2φ(x)1)

筛出欧拉函数和 n n n 以内的质数,处理出前缀和,然后暴力加即可。

代码
#pragma region
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
#define tr t[root]
#define lson t[root << 1]
#define rson t[root << 1 | 1]
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
#pragma endregion
const int maxn = 1e7 + 5;

int cnt = 0, prime[maxn];
bool mp[maxn];
void phi_table(int n, int* phi) {
    for (int i = 2; i <= n; i++) phi[i] = 0;
    phi[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (!phi[i]) {
            prime[++cnt] = i;
            for (int j = i; j <= n; j += i) {
                if (!phi[j]) phi[j] = j;
                phi[j] = phi[j] / i * (i - 1);
            }
        }
    }
}
int phi[maxn];
ll pre[maxn];
int main() {
    int n;
    scanf("%d", &n);
    phi_table(n, phi);
    rep(i, 1, n / 2) pre[i] = pre[i - 1] + 2 * phi[i];
    ll ans = 0;
    rep(i, 1, cnt) {
        int p = prime[i];
        if (p > n) break;
        ans += pre[n / p] - 1;
    }
    printf("%lld\n", ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值