C++ 如何快速求出n以内互质数的个数

题目描述

如果不同的整数X和Y的最大公约数为1,则称X和Y为互质数。显然,X和Y互质等价于Y和X互质。给出整数N,求1~N之间,有多少个数对(X,Y)是互质数。

例如N=5时,(1,2) , (1,3), (1,4), (1,5), (2,3), (2,5), (3,4), (3,5), (4,5)共9对数是互质数。


思路

很容易想到暴搜,两重循环,模拟 x 和 y ,再判定是否互质,但数据一旦过大,就会超时,那有不有什么快速的方法解题

就要引出主题欧拉函数了(如果不了解,点击查看),欧拉函数求的是 n 以内与 n 互质数的个数,那么只需要循环一遍 n ,累加其欧拉函数之和就可以迅速求出结果了。


代码

结合代码理解

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
 
int n , ans , pr[10007] , ph[10007] , cnt ;
bool vis[10007] ;
 
int main() {//结合了欧拉筛法
    ph[1] = 1 ;
    scanf("%d", &n );
    for(int  i = 2 ; i <= n ; ++ i ) {//分解质因数和初始化
        if(!vis[i]) {
            cnt ++ ;
            pr[cnt] = i ;
            ph[i] = i - 1 ;
        }
        for(int j = 1 ; j <= cnt && i * pr[j] <= n ; ++ j ) {//欧拉筛法
            vis[ i * pr[j] ] = 1 ;
            if( i % pr[j] == 0 ) {
                ph[ pr[j] * i ] = ph[i] * pr[j] ;
                break;
            }
            else
                ph [ pr[j] * i] = ph[i] * (pr[j] - 1 );
        }
    }
    for(int i = 2 ; i <= n ; ++ i )
        ans += ph[i];//累加结果
    cout<<ans;
    return 0;
}

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值