You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于容斥公式的Mertens函数M(n)界估计方法的可行性探讨

基于容斥公式的Mertens函数M(n)界估计方法的可行性探讨

首先得说,你用容斥原理推导Mertens函数$M(n)$的思路相当巧妙,直接把$M(n)$和素数计数函数$\pi(n)$建立了直观联系,这是个很自然的切入角度。

先梳理下你推导的核心内容:
原始容斥表达式:
$$M(n)=1-\pi\left(n\right)+\sum_{p_{i}\leq\frac{n}{p_i}}\left(\pi\left(\frac{n}{p_{i}}\right)-i\right)-\sum_{p_{i}<p_{j}\leq\frac{n}{p_ip_j}}\left(\pi\left(\frac{n}{p_{i}p_{j}}\right)-j\right)+\sum_{p_{i}<p_{j}<p_{k}\leq\frac{n}{p_ip_jp_k}}\left(\pi\left(\frac{n}{p_{i}p_{j}p_{k}}\right)-k\right)-\dots$$

你后来将其拆分为两个大项:
$$M(n)=\left(-\pi\left(n\right)+\sum_{p_{i}\leq\frac{n}{p_i}}\pi\left(\frac{n}{p_{i}}\right)-\sum_{p_{i}<p_{j}\leq\frac{n}{p_ip_j}}\pi\left(\frac{n}{p_{i}p_{j}}\right)+\sum_{p_{i}<p_{j}<p_{k}\leq\frac{n}{p_ip_jp_k}}\pi\left(\frac{n}{p_{i}p_{j}p_{k}}\right)-\dots\right)-\left(\sum_{p_{i}\leq\frac{n}{p_i}}i-\sum_{p_{i}<p_{j}\leq\frac{n}{p_ip_j}}j+\sum_{p_{i}<p_{j}<p_{k}\leq\frac{n}{p_ip_jp_k}}k-\dots\right)$$

代入素数定理近似后得到了表达式(1),而且你通过数值计算发现,拆分后的两个表达式在x轴附近呈现准对称振荡的特点——这个观察非常有价值,这种抵消效应或许能帮你简化后续的界估计工作。

关于方法可行性的分析

你的思路理论上完全可行:

  • 像Dussart给出的$\pi(x)$紧界$\frac{x}{\log x -1} < \pi(x) < \frac{x}{\log x -1.1}$,代入后确实能给每一项套上上下界,进而得到$M(n)$的区间估计;
  • 对于小$n$的场景,这种方法能给出精确的计算结果,数值观察到的抵消效应还能进一步优化计算效率。

但也需要注意几个核心难点:

  1. 截断误差控制:容斥表达式是无穷级数,实际计算只能取有限项,你需要严格估计截断后剩余项的贡献,否则得到的界会不够严谨。而且随着$n$增大,需要考虑的素数组合项数会急剧增长,误差控制的难度也会直线上升。
  2. 计算复杂度:如果要得到严格的界,每一项代入$\pi(x)$的界后,需要处理多层求和的上下界,计算量会非常大,尤其是大$n$场景下,这种方法的效率远低于成熟的解析数论方法。
  3. 现有方法的对比:目前学界对$M(n)$的非平凡界(比如$M(n)=O(n^{1/2+\epsilon})$,或者更紧的指数型界)都是通过解析数论方法得到的——利用黎曼ζ函数的零点分布、复积分技巧等,这些方法能更高效地得到大$n$下的渐近界,而容斥方法更适合小$n$的精确计算或者启发式分析。

后续建议

如果你坚持走容斥这条路,可以试试这几个方向:

  • 先聚焦于估计截断误差,比如证明当素数乘积超过某个阈值后,剩余项的绝对值可以被某个小量控制;
  • 利用你观察到的两个拆分表达式的准对称特性,尝试证明它们的绝对值相近,从而把$M(n)$的界转化为其中一个表达式的界,大幅简化计算;
  • 先在小$n$范围内验证方法的有效性,再逐步推广到大$n$场景。

如果你的目标是得到大$n$下的非平凡界,那解析数论的方法会更成熟高效,建议参考相关经典文献(比如关于Mertens函数的渐近分析、ζ函数零点的应用)。

你用于数值实验的代码

@author: juanmoreno

import math
import matplotlib.pyplot as plt

def sieve_of_eratosthenes(n):
    is_prime = [True] * (n + 1)
    is_prime[0] = is_prime[1] = False
    primes = []
    for p in range(2, int(math.sqrt(n)) + 1):
        if is_prime[p]:
            for i in range(p * p, n + 1, p):
                is_prime[i] = False
    for i in range(2, n + 1):
        if is_prime[i]:
            primes.append(i)
    return primes

def calculate_expression_1(n):
    return (-n / math.log(n))

def calculate_expression_2(n, primes):
    result = 0
    result_2 = 0
    for pi in primes:
        if pi < n / pi:
            result += (n / (pi * (math.log(n) - math.log(pi))))
            result_2 -= primes.index(pi)
    return result, result_2

def calculate_expression_3(n, primes):
    result = 0
    result_3 = 0
    for i in range(len(primes)):
        for j in range(i + 1, len(primes)):
            pij = primes[i] * primes[j]
            if primes[j] < n / pij:
                result -= (n / (pij * (math.log(n) -
                math.log(primes[i]) - math.log(primes[j]))))
                result_3 += j
    return result, result_3

def calculate_expression_4(n, primes):
    result = 0
    result_4 = 0
    for i in range(len(primes)):
        for j in range(i + 1, len(primes)):
            pij = primes[i] * primes[j]
            if pij < n / pij:
                for k in range(j + 1, len(primes)):
                    pijk = pij * primes[k]
                    if primes[k] <= n / pijk:
                        result += (n / (pijk * (math.log(n) -
                        math.log(primes[i]) - math.log(primes[j]) - math.log(primes[k]))))
                        result_4 -= k
    return result, result_4

def calculate_expression_5(n, primes):
    result = 0
    result_5 = 0
    for i in range(len(primes)):
        for j in range(i + 1, len(primes)):
            pij = primes[i] * primes[j]
            if pij < n / pij:
                for k in range(j + 1, len(primes)):
                    pijk = pij * primes[k]
                    if pijk < n / pijk:
                        for l in range(k + 1, len(primes)):
                            pijkl = pijk * primes[l]
                            if primes[l] <= n / pijkl:
                                result -= (n / (pijkl * (math.log(n) - math.log(primes[i]) - math.log(primes[j]) - math.log(primes[k])-math.log(primes[l]))))
                                result_5 += l
    return result, result_5

# Create lists to store results and square roots of n
results_1 = []
results_2 = []
sqrt_n = []
x_axis = []

for n in range(2, 10001):
    primes = sieve_of_eratosthenes(n)
    result1 = calculate_expression_1(n)
    result2 = calculate_expression_2(n, primes)[0]
    result3 = calculate_expression_3(n, primes)[0]
    result4 = calculate_expression_4(n, primes)[0]
    result5 = calculate_expression_5(n, primes)[0]
    final_result_1 =1 + result1 + result2 + result3 + result4 + result5

    result21 = calculate_expression_2(n, primes)[1]
    result31 = calculate_expression_3(n, primes)[1]
    result41 = calculate_expression_4(n, primes)[1]
    result51 = calculate_expression_5(n, primes)[1]
    final_result_2 = result21 + result31 + result41 + result51

    results_1.append(final_result_1)
    results_2.append(final_result_2)
    sqrt_n.append(math.sqrt(n))
    x_axis.append(0)

# Create a plot to compare results and sqrt(n)
plt.figure(figsize=(10, 6))
plt.plot(range(2, 10001), results_1, label='Expression (1)',
linewidth=2)
plt.plot(range(2, 10001), results_2, label='Expression (2)',
linewidth=2)
plt.plot(range(2, 10001), sqrt_n, label='square root of n',
linestyle='--', linewidth=2)
plt.plot(range(2, 10001), x_axis, label='x-axis', linestyle='--',
linewidth=2)
plt.xlabel('n')
plt.ylabel('Value')
plt.legend()
plt.title('Comparison of Final Result and x-axis')
plt.grid(True)
plt.show()

备注:内容来源于stack exchange,提问作者Juan Moreno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 14:49:50