P2303 [SDOI2012] Longge 的问题
题目描述
现在问题来了:给定一个整数 \(n\),你需要求出 \(\sum\limits_{i=1}^n \gcd(i, n)\),其中 \(\gcd(i, n)\) 表示 \(i\) 和 \(n\) 的最大公因数。
分析
- 从上述推导可知我们所求\(S(n)=\sum_{j|n} j\varphi({n\over j})\tag{1}\),后续推导参考:【洛谷题解】P2303 [SDOi2012]Longge的问题 - 粉兔 - 博客园
-
在欧拉函数的计算中有如下定理:
若 \(a\)的唯一质因数分解为 \(a=p_1^{k_1}\times p_2^{k_2}\times\cdots\times p_m^{k_m}\),则 \(a\)的欧拉函数值为 \(\varphi(a)=(p_1^{k_1}-p_1{k_1-1})\times(p_2^{k_2}-p_2^{k_2-1})\times\cdots\times(p_m^{k_m}-p_m^{k_m-1})\),其等价表示形式如下:\[\varphi(a)=a\prod_{p|a}(1-{1\over p})=a\prod_{p|a}{p-1\over p} \] -
因此:
\[{\varphi(d)\over d}=\prod_{p|d}{p-1\over p} \] -
代回原式:
\[S(n)=n\sum_{d|n}\prod_{p|d}{p-1\over p} \]内层的乘积只关心质数 \(p\)是否出现在 \(d\)中,并不关心它在 \(d\)中出现了多少次。
-
设 \(n=p_1^{b_1}p_2^{b_2}\cdots p_m^{b_m}\),那么 \(n\)的任意因子 \(d\)可以唯一分解为 \(d=p_1^{c_1}p_2^{c_2}\cdots p_m^{c_m}\),其中一定有 \(0\leq c_i\leq b_i\)。
-
定义 \(f_i={p_i-1\over p_i}\),如果 \(c_i=0\),说明 \(p_i\)不在 \(d\)的质因数分解中,对乘积没有贡献;如果 \(c_i>0\),则贡献一个 \(f_i\),因此:
\[{\varphi(d)\over d}=\prod_{i=1}^m f_i^{[c_i>0]};[c_i>0]=\begin{cases}0,\ c_i=0\\1,\ c_i>0\end{cases} \]所以每个 \(p_i\)对应两种情况:
| \(c_i\)的选择 | 选择数量 | 对\({\varphi(d)\over d}\)的贡献 |
|---|---|---|
| \(c_i=0\) | \(1\)种 | \(1\) |
| \(1\leq c_i\leq b_i\) | \(b_i\)种 | \(f_i\) |
- 固定一个质因数 \(p_i\),关于指数 \(c_i\)的选择,其贡献之和为:\[\sum_{c_i=0}^{b_i}f_i^{[c_i>0]} \]
展开就是
由于不同是引述的指数 \(c_1,c_2,\cdots,c_m\)可以独立选择,整个多重求和就能拆成乘积:
最终得到:
#include <iostream>
#include <cstdint>
#include <cinttypes>
// using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
int main() {
u32 n;
scanf("%", SCNu32, &n);
u32 x = n;
u64 ans = n;
for (u32 p = 2; p <= x / p; p++) {
if (x % p == 0) {
u32 b = 0;
while (x % p == 0) {
x /= p;
b++;
}
ans = ans / p * (p + b * (p - 1));
}
}
// 如果 x > 1 说明还剩下一个指数为 1 的质因子
if (x > 1) {
u32 p = x;
u32 b = 1;
ans = ans / p * (p + b * (p - 1));
}
printf("%" PRIu32 "\n", ans);
return 0;
}
- 时间复杂度:\([O(log\ n),O(\sqrt{n})]\)
- 空间复杂度:\(O(1)\)

P2303 [SDOI2012] Longge 的问题
浙公网安备 33010602011771号