跳转至

数论基础(四)数论函数

章节概述

数论函数是定义在正整数上的函数,在数论研究中占有重要地位。本章将介绍两个最重要的数论函数:欧拉函数 φ(n) 和莫比乌斯函数 μ(n),以及它们的计算方法和应用。

学习目标

  • 理解欧拉函数的定义和性质
  • 掌握欧拉函数的计算方法(筛法)
  • 理解莫比乌斯函数的定义和性质
  • 掌握莫比乌斯函数的计算方法
  • 了解数论函数在组合数学和算法中的应用
  • 掌握欧拉定理和费马小定理

(一)欧拉函数

欧拉函数的定义

欧拉函数 φ(n) 定义为:小于等于 n 的正整数中与 n 互质的数的个数。

数学表达式:

φ(n) = |{x ∈ ℤ⁺ : 1 ≤ x ≤ n, gcd(x, n) = 1}|

基本性质

性质1:质数的欧拉函数

如果 p 是质数,则:

φ(p) = p - 1

原因:质数 p 与所有小于 p 的正整数都互质。

性质2:质数幂的欧拉函数

如果 p 是质数,k ≥ 1,则:

φ(pᵏ) = pᵏ - pᵏ⁻¹ = pᵏ(1 - 1/p)

原因:在 1 到 pᵏ 中,只有 p 的倍数(p, 2p, 3p, ..., pᵏ⁻¹p)与 pᵏ 不互质,共有 pᵏ⁻¹ 个。

性质3:积性函数

如果 gcd(m, n) = 1,则:

φ(m × n) = φ(m) × φ(n)

性质4:欧拉函数的值

对于任意 n ≥ 3,φ(n) 是偶数。

性质5:欧拉函数的求和

Σ[d|n] φ(d) = n

计算欧拉函数

方法一:分解质因数法

原理:利用欧拉函数的积性性质

如果 n = p₁^a₁ × p₂^a₂ × ... × pₖ^aₖ,则:

φ(n) = n × Π(1 - 1/pᵢ)

def euler_phi(n):
    """
    计算欧拉函数 φ(n)(分解质因数法)

    参数:
        n: 正整数

    返回:
        int: φ(n) 的值

    时间复杂度: O(√n)

    示例:
        >>> euler_phi(1)
        1
        >>> euler_phi(7)
        6
        >>> euler_phi(12)
        4  # 1, 5, 7, 11
        >>> euler_phi(100)
        40
    """
    if n == 0:
        return 0

    result = n
    p = 2

    while p * p <= n:
        if n % p == 0:
            # p 是 n 的质因数
            while n % p == 0:
                n = n // p
            result = result // p * (p - 1)
        p += 1

    # 如果剩下的 n 是质数
    if n > 1:
        result = result // n * (n - 1)

    return result

方法二:筛法(预处理)

应用场景:需要计算多个数的欧拉函数

def euler_phi_sieve(n):
    """
    筛法求 1 到 n 的欧拉函数

    参数:
        n: 正整数

    返回:
        list: phi[i] 表示 φ(i)

    时间复杂度: O(n log log n)
    空间复杂度: O(n)

    示例:
        >>> phi = euler_phi_sieve(20)
        >>> print(phi)
        [0, 1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8]
    """
    phi = list(range(n + 1))
    is_prime = [True] * (n + 1)
    is_prime[0] = is_prime[1] = False

    for i in range(2, n + 1):
        if is_prime[i]:
            # i 是质数,更新所有 i 的倍数
            for j in range(i, n + 1, i):
                is_prime[j] = (j == i)
                phi[j] = phi[j] // i * (i - 1)

    return phi

方法三:线性筛法(欧拉筛)

def euler_phi_linear(n):
    """
    线性筛法求 1 到 n 的欧拉函数

    参数:
        n: 正整数

    返回:
        list: phi[i] 表示 φ(i)

    时间复杂度: O(n)
    空间复杂度: O(n)

    示例:
        >>> phi = euler_phi_linear(20)
        >>> print(phi)
        [0, 1, 1, 2, 2, 4, 2, 6, 4, 6, 4, 10, 4, 12, 6, 8, 8, 16, 6, 18, 8]
    """
    phi = [0] * (n + 1)
    primes = []
    is_composite = [False] * (n + 1)

    phi[1] = 1

    for i in range(2, n + 1):
        if not is_composite[i]:
            primes.append(i)
            phi[i] = i - 1

        for p in primes:
            if i * p > n:
                break
            is_composite[i * p] = True

            if i % p == 0:
                # p 是 i 的质因数
                phi[i * p] = phi[i] * p
                break
            else:
                # i 和 p 互质
                phi[i * p] = phi[i] * phi[p]

    return phi

欧拉定理

定理:如果 gcd(a, n) = 1,则:

a^φ(n) ≡ 1 (mod n)

证明:利用群论或构造性证明

应用: - 求模逆元 - RSA 加密算法 - 简化幂运算

def euler_theorem(a, n):
    """
    验证欧拉定理

    参数:
        a, n: 整数,gcd(a, n) = 1

    返回:
        bool: 如果 a^φ(n) ≡ 1 (mod n) 返回 True
    """
    if gcd(a, n) != 1:
        return False

    phi = euler_phi(n)
    return mod_pow(a, phi, n) == 1

费马小定理

定理:如果 p 是质数,且 gcd(a, p) = 1,则:

a^(p-1) ≡ 1 (mod p)

推论:

a^p ≡ a (mod p)

注意:这是欧拉定理在 n = p(质数)时的特例。

欧拉函数的应用

应用1:求模逆元

def mod_inverse_using_euler(a, n):
    """
    使用欧拉定理求模逆元

    参数:
        a: 整数
        n: 正整数

    返回:
        int: a 模 n 的逆元
             如果逆元不存在返回 None
    """
    if gcd(a, n) != 1:
        return None

    phi = euler_phi(n)
    return mod_pow(a, phi - 1, n)

应用2:简分数计数

问题:分母为 n 的真分数(分子分母互质)有多少个?

def count_reduced_fractions(n):
    """
    计算分母为 n 的真分数个数

    参数:
        n: 分母

    返回:
        int: 真分数的个数
    """
    return euler_phi(n)

(二)莫比乌斯函数

莫比乌斯函数的定义

莫比乌斯函数 μ(n) 定义为:

规则: - μ(1) = 1 - 如果 n 有平方因子(即存在质数 p,使 p² | n),则 μ(n) = 0 - 如果 n 是 k 个不同质数的乘积,则 μ(n) = (-1)^k

基本性质

性质1:积性函数

如果 gcd(m, n) = 1,则:

μ(m × n) = μ(m) × μ(n)

性质2:莫比乌斯函数的求和

Σ[d|n] μ(d) = 
    1, 如果 n = 1
    0, 如果 n > 1

性质3:与欧拉函数的关系

φ(n) = Σ[d|n] μ(d) × (n/d)

计算莫比乌斯函数

def mobius(n):
    """
    计算莫比乌斯函数 μ(n)

    参数:
        n: 正整数

    返回:
        int: μ(n) 的值(-1, 0, 或 1)

    时间复杂度: O(√n)

    示例:
        >>> mobius(1)
        1
        >>> mobius(2)
        -1
        >>> mobius(4)
        0
        >>> mobius(6)
        1
        >>> mobius(30)
        -1
    """
    if n == 1:
        return 1

    prime_factors = set()
    temp = n

    # 分解质因数
    for i in range(2, int(n**0.5) + 1):
        if temp % i == 0:
            count = 0
            while temp % i == 0:
                count += 1
                temp = temp // i
            if count > 1:
                return 0  # 有平方因子
            prime_factors.add(i)

    if temp > 1:
        prime_factors.add(temp)

    return (-1) ** len(prime_factors)

筛法求莫比乌斯函数

def mobius_sieve(n):
    """
    筛法求 1 到 n 的莫比乌斯函数

    参数:
        n: 正整数

    返回:
        list: mu[i] 表示 μ(i)

    时间复杂度: O(n log log n)
    空间复杂度: O(n)

    示例:
        >>> mu = mobius_sieve(20)
        >>> print(mu)
        [0, 1, -1, -1, 0, -1, 1, -1, 0, 0, 1, -1, 0, -1, 1, 1, 0, -1, 0, -1, 0]
    """
    mu = [0] * (n + 1)
    mu[1] = 1
    is_prime = [True] * (n + 1)
    is_prime[0] = is_prime[1] = False

    for i in range(2, n + 1):
        if is_prime[i]:
            # i 是质数
            for j in range(i, n + 1, i):
                is_prime[j] = (j == i)
                mu[j] *= -1
                mu[j * i] = 0

    return mu

莫比乌斯反演

定理:如果

f(n) = Σ[d|n] g(d)
则
g(n) = Σ[d|n] μ(d) × f(n/d)

应用:简化求和问题

def mobius_inversion(f, n):
    """
    莫比乌斯反演

    参数:
        f: 函数 f
        n: 正整数

    返回:
        int: g(n) 的值

    假设 f(n) = Σ[d|n] g(d)
    """
    result = 0
    for d in range(1, n + 1):
        if n % d == 0:
            result += mobius(d) * f(n // d)
    return result

莫比乌斯函数的应用

应用1:计算互质数对

问题:求 1 ≤ i, j ≤ n 且 gcd(i, j) = 1 的数对 (i, j) 的个数

def count_coprime_pairs(n):
    """
    计算 1 ≤ i, j ≤ n 且 gcd(i, j) = 1 的数对个数

    参数:
        n: 正整数

    返回:
        int: 互质数对的个数

    时间复杂度: O(n log n)
    """
    phi = euler_phi_sieve(n)
    # 互质数对个数 = 2 × Σ(φ(i)) - 1
    return 2 * sum(phi) - 1

应用2:容斥原理

莫比乌斯函数可以看作是容斥原理的数学表达。

(三)其他重要数论函数

约数函数 d(n)

定义:n 的正约数的个数

性质:如果 n = p₁^a₁ × p₂^a₂ × ... × pₖ^aₖ,则:

d(n) = (a₁ + 1) × (a₂ + 1) × ... × (aₖ + 1)

def divisor_count(n):
    """
    计算 n 的约数个数

    参数:
        n: 正整数

    返回:
        int: 约数的个数

    示例:
        >>> divisor_count(12)
        6  # 1, 2, 3, 4, 6, 12
    """
    factors = prime_factorization(n)
    count = 1
    for exp in factors.values():
        count *= (exp + 1)
    return count

约数和函数 σ(n)

定义:n 的所有正约数的和

性质:如果 n = p₁^a₁ × p₂^a₂ × ... × pₖ^aₖ,则:

σ(n) = Π(pᵢ^(aᵢ+1) - 1) / (pᵢ - 1)

def divisor_sum(n):
    """
    计算 n 的所有约数的和

    参数:
        n: 正整数

    返回:
        int: 所有约数的和

    示例:
        >>> divisor_sum(12)
        28  # 1 + 2 + 3 + 4 + 6 + 12 = 28
    """
    factors = prime_factorization(n)
    total = 1
    for p, exp in factors.items():
        total *= (p**(exp + 1) - 1) // (p - 1)
    return total

(四)实战应用

应用1:计算循环群的阶

问题:在模 n 下,与 n 互质的数构成一个乘法群,求这个群的阶。

def multiplicative_group_order(n):
    """
    计算模 n 乘法群的阶

    参数:
        n: 正整数

    返回:
        int: 群的阶(即 φ(n))
    """
    return euler_phi(n)

应用2:计算原根

问题:判断 g 是否是模 p 的原根

def is_primitive_root(g, p):
    """
    判断 g 是否是模 p 的原根

    参数:
        g: 候选原根
        p: 奇质数

    返回:
        bool: 如果是原根返回 True

    原根定义:g 模 p 的阶为 φ(p) = p-1
    """
    if g % p == 0:
        return False

    # 检查 g^((p-1)/q) ≠ 1 (mod p) 对所有 p-1 的质因数 q
    phi = p - 1
    factors = prime_factorization(phi)

    for q in factors.keys():
        if mod_pow(g, phi // q, p) == 1:
            return False

    return True

实战练习

练习1:计算多个数的欧拉函数

任务:使用筛法计算 1 到 100 的所有欧拉函数值

def exercise_1():
    """
    计算 1 到 100 的欧拉函数值
    """
    phi = euler_phi_sieve(100)
    for i in range(1, 101):
        print(f"φ({i}) = {phi[i]}")

练习2:验证欧拉函数的积性

任务:验证如果 gcd(m, n) = 1,则 φ(m × n) = φ(m) × φ(n)

def exercise_2():
    """
    验证欧拉函数的积性
    """
    for m in range(1, 50):
        for n in range(1, 50):
            if gcd(m, n) == 1:
                assert euler_phi(m * n) == euler_phi(m) * euler_phi(n)
    print("✓ 欧拉函数的积性验证通过")

练习3:计算互质概率

任务:随机选择两个正整数,求它们互质的概率

def estimate_coprime_probability(trials=10000):
    """
    估计两个随机整数互质的概率

    参数:
        trials: 试验次数

    返回:
        float: 估计的概率

    理论值:6/π² ≈ 0.6079
    """
    import random
    count = 0
    for _ in range(trials):
        a = random.randint(1, 1000)
        b = random.randint(1, 1000)
        if gcd(a, b) == 1:
            count += 1
    return count / trials

# 运行
print(estimate_coprime_probability())

章节小结

本章介绍了重要的数论函数:

  1. 欧拉函数:理解定义、性质和计算方法(筛法、线性筛法)
  2. 莫比乌斯函数:理解定义、性质和计算方法
  3. 欧拉定理和费马小定理:掌握其应用
  4. 其他数论函数:了解约数函数和约数和函数
  5. 莫比乌斯反演:理解其在求和问题中的应用

数论函数在组合数学、解析数论和算法设计中都有重要应用。

下一步

继续学习第五章:数论算法,学习质因数分解、勒让德符号、离散对数等高级算法。


重点提醒: - 欧拉函数是积性函数,可以用筛法高效计算 - 莫比乌斯函数用于容斥原理和莫比乌斯反演 - 欧拉定理和费马小定理是模运算的重要工具 - 线性筛法可以在 O(n) 时间内计算所有欧拉函数值