1 条题解

  • 0
    @ 2025-11-7 11:26:14

    题目大意

    我们称一个高斯整数 a+bia + b\text{i}(其中 a,ba, b 是整数)是整数 kk 的约数,如果存在另一个高斯整数 c+dic + d\text{i} 使得:

    (a+bi)(c+di)=k(a + b\text{i})(c + d\text{i}) = k

    给定 nn,求所有满足 a>0a > 0 的约数 a+bia + b\text{i}aa 之和(对 11nn 的所有 kk 求和)。

    问题分析

    高斯整数的约数

    在 Gaussian Integers(高斯整数)中,一个整数 kk 的约数 a+bia + b\text{i} 需要满足:

    • a,ba, b 是整数
    • a2+b2a^2 + b^2 整除 kk

    这是因为:

    $$(a + b\text{i})(c + d\text{i}) = (ac - bd) + (ad + bc)\text{i} = k $$

    由于 kk 是实数,所以 ad+bc=0ad + bc = 0,且 acbd=kac - bd = k。通过计算可以得到 k=(a2+b2)(c2+d2)/(a2+b2)k = (a^2 + b^2)(c^2 + d^2)/(a^2 + b^2) 的某种形式,实际上最终结论是:a2+b2a^2 + b^2 必须整除 kk

    更准确地说,z=a+biz = a + b\text{i}kk 的约数当且仅当 zz 的范数 N(z)=a2+b2N(z) = a^2 + b^2 整除 kk

    问题转化

    因此,原问题转化为: 对于每个 kk11nn,求所有满足 a>0a > 0a2+b2a^2 + b^2 整除 kkaa 之和。

    设答案为:

    $$\text{ans} = \sum_{k=1}^n \sum_{\substack{a>0 \\ a^2+b^2 \mid k}} a $$

    交换求和顺序:

    $$\text{ans} = \sum_{a=1}^n \sum_{b=-\infty}^{\infty} \sum_{\substack{k=1 \\ a^2+b^2 \mid k}}^n a \cdot [a>0] $$

    由于 a2+b2ka^2+b^2 \mid k,设 k=m(a2+b2)k = m(a^2+b^2),则:

    $$\text{ans} = \sum_{a=1}^n \sum_{b=-\infty}^{\infty} a \cdot \left\lfloor \frac{n}{a^2+b^2} \right\rfloor \cdot [a^2+b^2 \leq n] $$

    进一步简化

    由于表达式关于 bb 对称,我们可以只考虑 b0b \geq 0 然后乘以相应的系数:

    • b=0b = 0 时,贡献为 11
    • b>0b > 0 时,贡献为 22 倍(因为 bbb-b 都对应相同的 a2+b2a^2+b^2

    所以:

    $$\text{ans} = \sum_{a=1}^{\lfloor \sqrt{n} \rfloor} \sum_{b=0}^{\lfloor \sqrt{n-a^2} \rfloor} a \cdot c_b \cdot \left\lfloor \frac{n}{a^2+b^2} \right\rfloor $$

    其中 $c_b = \begin{cases} 1 & \text{if } b = 0 \\ 2 & \text{if } b > 0 \end{cases}$

    算法实现

    直接枚举(适合小数据)

    对于 n107n \leq 10^7,我们可以直接枚举 aabb

    #include <iostream>
    #include <cmath>
    using namespace std;
    
    const int MOD = 1004535809;
    
    int main() {
        int n;
        cin >> n;
        long long ans = 0;
        int sqrt_n = sqrt(n);
        
        for (int a = 1; a <= sqrt_n; a++) {
            for (int b = 0; a*a + b*b <= n; b++) {
                if (b == 0) {
                    ans = (ans + 1LL * a * (n / (a*a))) % MOD;
                } else {
                    ans = (ans + 2LL * a * (n / (a*a + b*b))) % MOD;
                }
            }
        }
        
        cout << ans << endl;
        return 0;
    }
    

    优化算法(适合大数据)

    对于 nn 达到 101010^{10} 的情况,我们需要更高效的算法。

    观察求和式:

    $$\text{ans} = \sum_{d=1}^n \left\lfloor \frac{n}{d} \right\rfloor \cdot f(d) $$

    其中 f(d)f(d) 表示所有满足 a2+b2=da^2+b^2 = da>0a > 0aa 之和(考虑 b=0b=0 贡献 11 倍,b>0b>0 贡献 22 倍)。

    我们可以用数论分块来优化,预处理 f(d)f(d) 的前缀和。

    复杂度分析

    • 直接枚举O(n)O(n) 对于 n107n \leq 10^7 可行
    • 优化算法O(n2/3)O(n^{2/3})O(n)O(\sqrt{n}) 对于更大的 nn

    总结

    本题的关键在于理解高斯整数约数与范数 a2+b2a^2+b^2 的关系,通过交换求和顺序将问题转化为数论分块的形式,从而设计出高效的算法。

    对于竞赛中的不同数据范围,需要选择相应复杂度的算法来实现。

    • 1

    信息

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