1 条题解

  • 0
    @ 2025-11-7 11:32:31

    题目分析

    题目定义了一个函数 f(x)f(x),其性质明确表明它是一个积性函数

    1. f(1)=1f(1) = 1
    2. 在质数幂 pcp^c 处的取值定义为 f(pc)=pcf(p^c) = p \oplus cpp 为质数,\oplus 为异或运算)
    3. aabb 互质时,f(ab)=f(a)f(b)f(ab) = f(a)f(b)

    我们的目标是求出这个积性函数 f(i)f(i) 的前缀和,即 S(n)=i=1nf(i)S(n) = \sum_{i=1}^{n} f(i),并对 109+710^9+7 取模。

    数据范围 n1010n \leq 10^{10} 是一个强烈的信号,表明我们需要使用亚线性时间复杂度的算法。

    算法选择

    对于积性函数前缀和问题,在 nn 很大时,主要有两种强大的筛法:

    1. 杜教筛:适用于存在另一个积性函数 gg,使得 fgf * g 的前缀和易于计算的情况。
    2. Min_25筛:适用性更广,要求积性函数 ff 在质数 pp 和质数幂 pkp^k 处的表达式是一个关于 pp 的低次多项式,或者是易于计算的。

    分析我们的函数 ff

    • 在质数点 pp (即 p1p^1) 处,f(p)=p1f(p) = p \oplus 1
    • 这个表达式 p1p \oplus 1 不是一个关于 pp 的多项式。它依赖于 pp 的二进制表示。

    因此,标准的 Min_25 筛模板不能直接应用。我们需要对其进行改造。

    改造的 Min_25 筛思路

    标准的 Min_25 筛将问题分为两部分:

    1. 质数部分和:计算所有质数 pnp \le nf(p)f(p) 之和。
    2. 合数部分和:通过枚举最小质因子递归计算。

    难点在于第一部分。标准 Min_25 筛使用多项式来拟合质数处的函数值,但 f(p)=p1f(p)=p \oplus 1 无法用多项式拟合。

    解决方案: 我们可以利用 按位处理 (Digit DP) 的思想。注意到 f(p)=p1f(p) = p \oplus 1 的值只与 pp 的二进制位有关。我们可以将 pp 按二进制位拆分,根据每一位是 0 还是 1 来分类讨论它对 f(p)f(p) 的贡献。

    具体地,在 Min_25 筛的第一阶段(“筛质数”阶段),我们不再维护一个单一的多项式函数,而是维护一个状态,该状态记录了在当前处理的数位下,满足条件的质数的某种“贡献和”。

    这个过程可以看作是一个数位 DPMin_25 筛的结合。我们定义状态 dp[pos][tight][...]

    • pos:当前正在处理的二进制位。
    • tight:当前是否受到 nn 的限制。
    • 其他状态可能需要记录当前已经累积的质数个数、当前累积的 f(p)f(p) 值等。

    通过这个 DP,我们可以“数”出所有小于等于 nn 的质数 ppf(p)f(p) 之和。

    算法流程

    1. 预处理

      • 使用线性筛预处理出 n\sqrt{n} 以内的所有质数。
      • 初始化 Min_25 筛和数位 DP 所需的数据结构。
    2. 计算质数部分和 SprimeS_{\text{prime}}

      • 使用结合了数位 DP 思想的 Min_25 筛,计算 pnf(p)=pn(p1)\sum_{p \le n} f(p) = \sum_{p \le n} (p \oplus 1)
      • 这是整个算法的核心和最复杂的部分。
    3. 计算合数部分和 ScompS_{\text{comp}}

      • 使用标准的 Min_25 筛第二部分流程,递归地枚举合数的最小质因子及其指数。
      • 对于一个合数,设其最小质因子为 pp,指数为 cc,剩余部分为 mm(与 pp 互质),则 f(pcm)=f(pc)f(m)f(p^c m) = f(p^c) f(m)
      • 这里 f(pc)=pcf(p^c) = p \oplus c 是已知的,f(m)f(m) 可以通过递归或查表得到。
    4. 合并结果

      • 总的前缀和 S(n)=1+Sprime+ScompS(n) = 1 + S_{\text{prime}} + S_{\text{comp}}
      • 最终结果对 109+710^9+7 取模。

    复杂度分析

    • 改造后的 Min_25 筛(结合数位 DP)的时间复杂度仍然为 O(n3/4logn)O(\frac{n^{3/4}}{\log n})O(n1ϵ)O(n^{1-\epsilon}),但其常数会大很多,因为状态转移涉及二进制位操作。
    • 空间复杂度为 O(n)O(\sqrt{n})

    代码实现要点(伪代码)

    MOD = 10**9+7
    
    def precompute_primes(sqrt_n):
        # 线性筛获取 sqrt(n) 内的质数
    
    def digit_dp_min25(n):
        # 将 n 转换为二进制
        bits = bin(n)[2:]
        L = len(bits)
        
        # dp[pos][tight][cnt][sum] 或其他状态定义
        dp = initialize_dp_state()
        dp[0][True][...] = initial_state
        
        for pos in range(L):
            for tight in [True, False]:
                for ... in state: # 遍历其他状态
                    if dp[pos][tight][...] is valid:
                        current_bit = int(bits[pos]) if tight else 1
                        for next_bit in [0, 1]:
                            if next_bit <= current_bit:
                                new_tight = tight and (next_bit == current_bit)
                                # 根据 next_bit 更新状态(例如,对质数个数、f(p)和的贡献)
                                update_dp_state(...)
        
        return final_result_from_dp
    
    def min25_sieve_part2(n, primes):
        # 使用递归或迭代计算合数部分的贡献
        # G(n, k) 表示从第 k 个质数开始,最小质因子 >= primes[k] 的合数的 f(i) 和
        # G(n, k) = sum_{j>=k} sum_{c>=1, e = primes[j]^c <= n} [ f(e) * (1 + G(floor(n/e), j+1)) ]
        ...
    
    def main(n):
        if n == 0: return 0
        primes = precompute_primes(int(n**0.5)+1)
        S_prime = digit_dp_min25(n) # 计算所有质数p的 f(p)=p XOR 1 的和
        S_comp = min25_sieve_part2(n, primes)
        return (1 + S_prime + S_comp) % MOD
    

    总结

    本题是一道非常具有挑战性的数论题目,它考察了选手对积性函数、Min_25 筛原理的深刻理解,以及将数位 DP 思想灵活应用于解决非标准形式函数求和问题的能力。其核心创新点在于通过数位 DP 来克服 Min_25 筛对质数点函数形式的限制。

    • 1

    信息

    ID
    5064
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者