P2303 [SDOI2012] Longge 的问题

题目描述


现在问题来了:给定一个整数 \(n\),你需要求出 \(\sum\limits_{i=1}^n \gcd(i, n)\),其中 \(\gcd(i, n)\) 表示 \(i\) 和 \(n\) 的最大公因数。

分析


\[\begin{flalign} & \quad\sum_{i=1}^ngcd(i,n)\\ & =\sum_{j=1}^n(j\times \sum_{i=1}^n[gcd(i,n)=j])\\ & =\sum_{j=1}^n(j\times \sum_{i=1}^n[gcd({i\over j},{n\over j})=1])\\ & =\sum_{j|n}(j\times \varphi({n\over j}))& \end{flalign} \]

\[\begin{flalign} & let\ d = {n\over j}\rightarrow j={n\over d}\\ & S(n)=\sum_{d|n}{n\over d}\varphi(d)\\ & \quad\quad\ = n\sum_{d|n}{\varphi(d)\over d}& \end{flalign} \]

  • 在欧拉函数的计算中有如下定理:
    若 \(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]} \]

展开就是

\[1+\underbrace{f_i+f_i+\cdots+f_i}_{b_i个}=1+b_if_i \]

由于不同是引述的指数 \(c_1,c_2,\cdots,c_m\)可以独立选择,整个多重求和就能拆成乘积:

\[\sum_{d|n}{\varphi(d)\over d}=\prod_{i=1}^m(1+b_i{p_i-1\over p_i}) \]

最终得到:

\[\boxed{S(n)=n\prod_{i=1}^m(1+b_i{p_i-1\over p_i})}\leftrightarrow \boxed{S(n)=n\prod_{i=1}^m{(b_i+1)p_i-b_i\over p_i}} \]

#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)\)

参考资料


posted @ 2026-09-10 11:26  chen_xing  阅读(7)  评论(0)    收藏  举报