洛谷 P2303:[SDOI2012] Longge 的问题 ← 欧拉函数

【题目来源】
https://www.luogu.com.cn/problem/P2303

【题目描述】
给定一个整数 n,你需要求出 ∑ gcd(i,n),i=1~n。其中 gcd(i,n) 表示 i 和 n 的最大公因数。

【输入格式】
输入只有一行一个整数,表示 n。

【输出格式】
输出一行一个整数表示答案。

【输入样例】
6

【输出样例】
15

【数据规模与约定】
对于 60% 的数据,保证 n≤2^16。
对于 100% 的数据,保证 1≤n<2^32。

【算法分析】
欧拉函数 φ(n) 是数论中的重要函数,用于计算 1~n 中与 n 互质的正整数的个数。特别地,当 n=1 时,φ(1)=1。质因数分解是欧拉函数计算的核心步骤。计算结果可能超出 int 范围,对大数需使用 long long。C++实现欧拉函数的两种经典方法如下所示。
(1)质因数分解法

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

int oula_phi(int x) {
    int ans=x;
    for(int i=2; i*i<=x; i++) {
        if(x%i==0) {
            ans=ans/i*(i-1);
            while(x%i==0) x/=i;
        }
    }
    if(x>1) ans=ans/x*(x-1);
    return ans;
}

int main() {
    int x;
    cin>>x;
    cout<<oula_phi(x);
    
    return 0;
}

/*
in:10
out:4
*/

(2)优化版筛法

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

const int maxn=1e6+5;
int phi[maxn];

void oula_sieve_opt() {
    phi[1]=1;
    for(int i=2; i<maxn; i++) {
        if(!phi[i]) {
            for(int j=i; j<maxn; j+=i) {
                if(!phi[j]) phi[j]=j;
                phi[j]=phi[j]/i*(i-1);
            }
        }
    }
}

int main() {
    int x;
    cin>>x;
    oula_sieve_opt();
    cout<<phi[x];

    return 0;
}

/*
in:10
out:4
*/

【算法代码一:long long
代码中 #define int long long 是 C/C++ 中的预处理宏定义指令,其核心作用是将代码中所有的 int 类型标识符替换为 long long 类型。注意千万不要写成 #define long long int
++使用++++#define int long long 将 int 替换为 long long 后,需配合 signed main(){ }++ ++使用++,以避免使用 int main(){ } 时导致返回值类型错误。

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;

int oula_phi(int x) {
    int ans=x;
    for(int i=2; i*i<=x; i++) {
        if(x%i==0) {
            ans=ans/i*(i-1);
            while(x%i==0) x/=i;
        }
    }
    if(x>1) ans=ans/x*(x-1);
    return ans;
}

signed main() {
    int n,cnt=0;
    scanf("%lld",&n); //cin>>n;
    for(int i=1; i*i<=n; i++) {
        if(n%i==0) {
            cnt+=i*oula_phi(n/i);
            if(i!=n/i) cnt+=(n/i)*oula_phi(i);
        }
    }
    printf("%lld",cnt); //cout<<cnt<<endl;
    return 0;
}

/*
in:6
out:15
*/

【算法代码二:__int128
在提高+、省选及NOI赛题中,经常会遇到超级大的输入输出,此时若++使用 C/C++ 中的宏指令++++#define int __int128 将代码中所有的 int 类型替换为 __int128 类型,需配合 signed main(){ }++ ++使用++ ,否则将会导致使用 int main(){ } 时的返回值类型错误。
但是,__int128 类型无标准 I/O 支持,无法直接使用 cin / cout / scanf / printf,需手动实现读写函数。

cpp 复制代码
#include <bits/stdc++.h>
#define int __int128
using namespace std;

int oula_phi(int x) {
    int ans=x;
    for(int i=2; i*i<=x; i++) {
        if(x%i==0) {
            ans=ans/i*(i-1);
            while(x%i==0) x/=i;
        }
    }
    if(x>1) ans=ans/x*(x-1);
    return ans;
}

int read() { //fast read
    int x=0,f=1;
    char c=getchar();
    while(c<'0' || c>'9') { //!isdigit(c)
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9') { //isdigit(c)
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}

void print(int x) {
    if(x<0) putchar('-'), x=-x;
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

signed main() {
    int n,cnt=0;
    n=read();
    for(int i=1; i*i<=n; i++) {
        if(n%i==0) {
            cnt+=i*oula_phi(n/i);
            if(i!=n/i) cnt+=(n/i)*oula_phi(i);
        }
    }
    print(cnt);

    return 0;
}

/*
in:6
out:15
*/

【参考文献】
https://www.luogu.com.cn/problem/P5091
https://www.luogu.com.cn/problem/P2568
https://www.luogu.com.cn/problem/P2303

相关推荐
float_六七2 个月前
在处理欧拉函数时如何使用逆元
算法·数论·欧拉函数
HP-Patience7 个月前
【复平面】-复数相乘的几何性质
欧拉函数·复分析
IT 青年8 个月前
信息安全数学基础(14)欧拉函数
数学·信息安全·欧拉函数
Wei&Yan1 年前
蓝桥杯每日一题:最大公约数(欧拉函数)
数据结构·c++·算法·蓝桥杯·欧拉函数
卡布叻_周深1 年前
2024初三年后集训模拟测试4
dfs·贪心·双指针·欧拉函数·打表,找规律·大模拟·meet in middle
chirou_2 年前
算法基础-数学知识-欧拉函数、快速幂、扩展欧几里德、中国剩余定理
c++·算法·蓝桥杯·欧几里德·欧拉函数