1 条题解
-
0
题目大意
我们称一个高斯整数 (其中 是整数)是整数 的约数,如果存在另一个高斯整数 使得:
给定 ,求所有满足 的约数 的 之和(对 到 的所有 求和)。
问题分析
高斯整数的约数
在 Gaussian Integers(高斯整数)中,一个整数 的约数 需要满足:
- 是整数
- 整除
这是因为:
$$(a + b\text{i})(c + d\text{i}) = (ac - bd) + (ad + bc)\text{i} = k $$由于 是实数,所以 ,且 。通过计算可以得到 的某种形式,实际上最终结论是: 必须整除 。
更准确地说, 是 的约数当且仅当 的范数 整除 。
问题转化
因此,原问题转化为: 对于每个 从 到 ,求所有满足 且 整除 的 之和。
设答案为:
$$\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] $$由于 ,设 ,则:
$$\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] $$进一步简化
由于表达式关于 对称,我们可以只考虑 然后乘以相应的系数:
- 当 时,贡献为 倍
- 当 时,贡献为 倍(因为 和 都对应相同的 )
所以:
$$\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}$
算法实现
直接枚举(适合小数据)
对于 ,我们可以直接枚举 和 :
#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; }优化算法(适合大数据)
对于 达到 的情况,我们需要更高效的算法。
观察求和式:
$$\text{ans} = \sum_{d=1}^n \left\lfloor \frac{n}{d} \right\rfloor \cdot f(d) $$其中 表示所有满足 且 的 之和(考虑 贡献 倍, 贡献 倍)。
我们可以用数论分块来优化,预处理 的前缀和。
复杂度分析
- 直接枚举: 对于 可行
- 优化算法: 或 对于更大的
总结
本题的关键在于理解高斯整数约数与范数 的关系,通过交换求和顺序将问题转化为数论分块的形式,从而设计出高效的算法。
对于竞赛中的不同数据范围,需要选择相应复杂度的算法来实现。
- 1
信息
- ID
- 5063
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 5
- 已通过
- 1
- 上传者