题目链接

题目描述

给定多次询问,每次输入一个正整数 ,输出欧拉函数 ,即区间 内与 互质的整数个数。

解题思路

  • 欧拉函数公式:若 的不同质因子集合为 ,则

  • 做法(试除分解质因子)

    • 设答案 。从 开始试除,直到
    • 一旦发现质因子 ,就把 中的 全部除尽,并令
    • 试除结束后,若剩余的 ,说明 本身是一个质因子,同样令
  • 边界 为质数时

  • 复杂度:单次询问试除到 ,时间复杂度 ,空间复杂度 。多次询问可逐个独立处理。

代码

#include <bits/stdc++.h>
using namespace std;
using int64 = long long;

// 计算单个整数的欧拉函数 φ(n)
static inline int64 phi(int64 n) {
    if (n == 1) return 1;               // 边界:φ(1) = 1
    int64 ans = n;
    for (int64 p = 2; p * p <= n; ++p) {
        if (n % p == 0) {
            // 将质因子 p 的幂全部除尽
            while (n % p == 0) n /= p;
            // 按公式 ans = ans / p * (p - 1)
            ans = ans / p * (p - 1);
        }
    }
    // 若此时 n > 1,说明剩余的是一个大于 sqrt(原始 n) 的质因子
    if (n > 1) ans = ans / n * (n - 1);
    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int q; // 询问次数
    if (!(cin >> q)) return 0;
    while (q--) {
        long long n;
        cin >> n;
        cout << phi(n) << '\n';
    }
    return 0;
}
import java.util.*;

public class Main {
    // 计算单个整数的欧拉函数 φ(n)
    static long phi(long n) {
        if (n == 1) return 1; // 边界处理
        long ans = n;
        for (long p = 2; p * p <= n; ++p) {
            if (n % p == 0) {
                while (n % p == 0) n /= p; // 去掉质因子 p 的所有幂
                ans = ans / p * (p - 1);   // 按公式更新答案
            }
        }
        if (n > 1) ans = ans / n * (n - 1); // 处理剩余的大质因子
        return ans;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int q = sc.nextInt();
        while (q-- > 0) {
            long n = sc.nextLong();
            System.out.println(phi(n));
        }
    }
}
# 计算单个整数的欧拉函数 φ(n)
def phi(n: int) -> int:
    if n == 1:
        return 1  # 边界:φ(1) = 1
    ans = n
    p = 2
    # 试除到 sqrt(n)
    while p * p <= n:
        if n % p == 0:
            while n % p == 0:
                n //= p  # 去掉质因子 p 的所有幂
            ans = ans // p * (p - 1)  # 按公式更新答案
        p += 1
    # 若剩余 n > 1,则其为一个大质因子
    if n > 1:
        ans = ans // n * (n - 1)
    return ans


q = int(input())
for _ in range(q):
    n = int(input())
    print(phi(n))

算法及复杂度

  • 算法:分解 的不同质因子,按 更新答案。
  • 时间复杂度:单次
  • 空间复杂度