AcWing 220. 最大公约数 | 欧拉函数

传送门

题目描述

给定整数N,求1<=x,y<=N且GCD(x,y)为素数的数对(x,y)有多少对。

GCD(x,y)即求x,y的最大公约数。

输入格式

输入一个整数N

输出格式

输出一个整数,表示满足条件的数对数量。

数据范围

1≤N≤10^7

输入样例:
4
输出样例:
4

 

题解:本题要求1<=x,y<=N且GCD(x,y)为素数的数对(x,y)数量,相当于求:对于N以内的每一个素数p,1<=x,y<=N/p 中GCD(x,y)为1的数对(x,y)数量和。我们知道欧拉函数的定义是1~n中与n互质的数的个数,那么对于p,1<=x,y<=N/p 中GCD(x,y)为1的数对(x,y)数量为φ(1)+φ(2)...+φ(N/p),可以用前缀和计算。要注意:x,y大小关系无影响所以要*2,但x,y相同时只算一次所以要-1。题目就变成了求\[\sum_{p是素数}^{p≤n} 2*\sum_{i=1}^{n/p}φ(i) -1\]  也可以用\[\sum_{p是素数}^{p≤n} 2*\sum_{i=2}^{n/p}φ(i) +1\]。

    

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e7 + 10;
int v[N],prime[N];
ll sum[N],phi[N];
int cnt = 0;
int main() {
    int n;
    scanf("%d",&n);
    phi[1]=1;
    for (int i = 2; i <= n; i++) {
        if(!v[i]) {
            v[i] = i;prime[cnt++] = i;
            phi[i] = i-1;
        }
        for (int j = 0; j < cnt; j++) {
            if (prime[j] > v[i] || prime[j] > n/i) break;
            v[i*prime[j]] = prime[j];
            phi[i*prime[j]] = phi[i] * (i%prime[j]?prime[j]-1:prime[j]);
        }
    }
    for (int i = 1; i <= n; i++) 
        sum[i] = sum[i-1]+phi[i];
    ll ans = 0;
    for (int i = 0; i < cnt; i++) {
        int num = n/prime[i];
        ans += 2*sum[num]-1;
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/l999q/p/11367956.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值