疯狂 LCM(LCM SUM) - 线性筛题解

疯狂 LCM(LCM SUM) - 题解

Luogu 1891

线性筛见分割线以下。

题目回顾:

T T T 组数据,对于每组数据,给定整数 n n n,计算:

∑ i = 1 n lcm ⁡ ( i , n ) \sum_{i=1}^n \operatorname{lcm}(i, n) i=1nlcm(i,n)

数据保证 1 ≤ T ≤ 3 × 1 0 5 1 \le T \le 3 \times 10^5 1T3×105 1 ≤ n ≤ 1 0 6 1 \le n \le 10^6 1n106

分析:

推式子部分

先看看能不能直接把式子抓起来算。显然这条式子不能拿来直接算(直接算意味着单次查询 O ( n ) O(n) O(n),是不能接受的),必须推一下,使得能在合适的时间复杂度下处理。

∑ i = 1 n lcm ⁡ ( i , n ) = ∑ i = 1 n i n gcd ⁡ ( i , n ) = n ∑ i = 1 n i gcd ⁡ ( i , n ) = n ∑ d ∣ n ∑ i = 1 n i d [ gcd ⁡ ( i , n ) = d ] = n ∑ d ∣ n ∑ i = 1 n d i [ gcd ⁡ ( i , n d ) = 1 ] = n ∑ d ∣ n ∑ i = 1 d i [ gcd ⁡ ( i , d ) = 1 ] = n ( ∑ d ∣ n d φ ( d ) 2 + 1 2 ) = n 2 ( ∑ d ∣ n d φ ( d ) + 1 ) \begin{aligned} &\sum_{i=1}^n \operatorname{lcm}(i, n)\\ =&\sum_{i=1}^n \frac{in}{\gcd(i, n)}\\ =&n\sum_{i=1}^n \frac{i}{\gcd(i, n)}\\ =&n\sum_{d\mid n} \sum_{i=1}^n \frac id [\gcd(i, n) = d]\\ =&n\sum_{d\mid n} \sum_{i=1}^{\frac nd} i [\gcd(i, \frac nd) = 1]\\ =&n\sum_{d\mid n} \sum_{i=1}^d i [\gcd(i, d) = 1]\\ =&n(\sum_{d\mid n} \frac{d \varphi(d)}2 + \frac 12)\\ =&\frac n2(\sum_{d\mid n} d\varphi(d) + 1) \end{aligned} =======i=1nlcm(i,n)i=1ngcd(i,n)inni=1ngcd(i,n)indni=1ndi[gcd(i,n)=d]ndni=1dni[gcd(i,dn)=1]ndni=1di[gcd(i,d)=1]n(dn2dφ(d)+21)2n(dndφ(d)+1)

推到这里就够了,有些细节需要解释一下。两个 Q&A 对应着两个难点。

Q: 倒数第三步怎么来的,为什么突然从 n / d n/d n/d 跳跃到 d d d 去了?
A: 我们枚举 d d d 和枚举 n / d n/d n/d 等价,实际上都是在找 n n n 的约数。

Q: 我知道 ∑ i = 1 d i [ gcd ⁡ ( i , d ) = 1 ] \sum_{i=1}^d i [\gcd(i, d) = 1] i=1di[gcd(i,d)=1] 的意义是求与 d d d 互质的数之和,之前学过它等于 d φ ( d ) / 2 d\varphi(d)/2 dφ(d)/2,为什么后面还要加一个 1 / 2 1/2 1/2
A: 别忘了,那个结论里面 1 1 1 是个例外。它的约数个数和显然是 1 1 1,但是按公式算得到了 1 / 2 1/2 1/2。然后不管算哪一个 n n n,统计的时候都会统计 d = 1 d = 1 d=1,都会漏了 1 1 1 的另外一半 1 / 2 1/2 1/2,把它补上去就行了。

假设 f ( n ) = ∑ d ∣ n d φ ( d ) f(n) = \sum_{d\mid n} d\varphi(d) f(n)=dndφ(d),所求就是 n ( f ( n ) + 1 ) / 2 n(f(n) + 1)/2 n(f(n)+1)/2,如果预处理 f ( n ) f(n) f(n) 的值,就可以在 O ( 1 ) O(1) O(1) 的时间复杂度下解决问题。

线性筛部分

观察, n φ ( n ) n\varphi(n) nφ(n) 可以看作 i d ( n ) id(n) id(n) φ ( n ) \varphi(n) φ(n) 的积,根据积性函数的定义,我们容易知道两个积性函数的积是积性函数。

继续观察, f ( n ) f(n) f(n) 可以看作 n φ ( n ) n\varphi(n) nφ(n) 1 ( n ) 1(n) 1(n) 两个积性函数的狄利克雷卷积,那么 f ( n ) f(n) f(n) 就是积性函数。我们知道,只要是积性函数,就一定可以用 线性筛 O ( n ) O(n) O(n) 的时间复杂度下进行预处理。

显然 f ( 1 ) = 1 f(1) = 1 f(1)=1

假设 p p p 为质数。显然 f ( p ) = 1 + p ( p − 1 ) = p 2 − p + 1 f(p) = 1 + p(p-1) = p^2 - p + 1 f(p)=1+p(p1)=p2p+1

假设线性筛外层循环枚举到 i i i。若 p ∤ i p \nmid i pi,显然 f ( i p ) = f ( i ) f ( p ) f(ip) = f(i)f(p) f(ip)=f(i)f(p)

关键在于解决 p ∣ i p \mid i pi 的情况。这是本题第三个难点。


新方案

国际金大佬曾经给出过一种方案,下面是另一种方案。截止笔者撰写此篇题解时,该方案已被较广泛使用,但尚未有人写过针对此方案的题解。现在将一步步证明出来。

先上结论: f ( i p ) = f ( i ) + p 2 ( f ( i ) − f ( i / p ) ) f(ip) = f(i) + p^2(f(i)-f(i/p)) f(ip)=f(i)+p2(f(i)f(i/p))

注意到:

f ( p c ) = ∑ d ∣ p c d φ ( d ) = 1 + ∑ i = 1 c p i φ ( p i ) = 1 + ∑ i = 1 c p i ⋅ p i − 1 ( p − 1 ) = 1 + ∑ i = 1 c p 2 i − p 2 i − 1 = 1 − p + p 2 − p 3 + p 4 + ⋯ − p 2 c − 1 + p 2 c = ∑ i = 0 2 c ( − p ) i \begin{aligned} &f(p^c)\\ =& \sum_{d\mid p^c} d\varphi(d)\\ =& 1 + \sum_{i=1}^c p^i\varphi(p^i)\\ =& 1 + \sum_{i=1}^c p^i \cdot p^{i-1}(p-1)\\ =& 1 + \sum_{i=1}^c p^{2i}-p^{2i-1}\\ =& 1 - p + p^2 - p^3 + p^4 + \cdots - p^{2c-1} + p^{2c}\\ =& \sum_{i=0}^{2c} (-p)^i \end{aligned} ======f(pc)dpcdφ(d)1+i=1cpiφ(pi)1+i=1cpipi1(p1)1+i=1cp2ip2i11p+p2p3+p4+p2c1+p2ci=02c(p)i

假设 i = a ⋅ p c i = a \cdot p^c i=apc,那么 f ( i ) = f ( a ) f ( p c ) f(i) = f(a)f(p^c) f(i)=f(a)f(pc) f ( i / p ) = f ( a ) f ( p c − 1 ) f(i/p) = f(a)f(p^{c-1}) f(i/p)=f(a)f(pc1) f ( i p ) = f ( a ) f ( p c + 1 ) f(ip) = f(a)f(p^{c+1}) f(ip)=f(a)f(pc+1)。进而得到:

f ( i p ) = f ( a ) f ( p c + 1 ) = f ( a ) ∑ i = 0 2 c + 2 ( − p ) i = f ( a ) ( ∑ i = 0 2 c ( − p ) i + ∑ i = 2 2 c + 2 ( − p ) i − ∑ i = 2 2 c ( − p ) i ) = f ( a ) ( ∑ i = 0 2 c ( − p ) i + p 2 ∑ i = 0 2 c ( − p ) i − p 2 ∑ i = 0 2 c − 2 ( − p ) i ) = f ( a ) ( f ( p c ) + p 2 f ( p c ) − p 2 f ( p c − 1 ) ) = f ( a ) f ( p c ) + p 2 ( f ( a ) f ( p c ) − f ( a ) f ( p c − 1 ) ) = f ( i ) + p 2 ( f ( i ) − f ( i / p ) ) \begin{aligned} &f(ip)\\ =& f(a)f(p^{c+1})\\ =& f(a)\sum_{i=0}^{2c+2}(-p)^i\\ =& f(a)(\sum_{i=0}^{2c}(-p)^i + \sum_{i=2}^{2c+2}(-p)^i - \sum_{i=2}^{2c}(-p)^i)\\ =& f(a)(\sum_{i=0}^{2c}(-p)^i + p^2\sum_{i=0}^{2c}(-p)^i - p^2\sum_{i=0}^{2c-2}(-p)^i)\\ =& f(a)(f(p^c) + p^2 f(p^c) - p^2 f(p^{c-1}))\\ =& f(a)f(p^c) + p^2(f(a)f(p^c)-f(a)f(p^{c-1}))\\ =& f(i) + p^2(f(i)-f(i/p)) \end{aligned} =======f(ip)f(a)f(pc+1)f(a)i=02c+2(p)if(a)(i=02c(p)i+i=22c+2(p)ii=22c(p)i)f(a)(i=02c(p)i+p2i=02c(p)ip2i=02c2(p)i)f(a)(f(pc)+p2f(pc)p2f(pc1))f(a)f(pc)+p2(f(a)f(pc)f(a)f(pc1))f(i)+p2(f(i)f(i/p))

容斥大法妙。

f ( i p ) = f ( i ) + p 2 ( f ( i ) − f ( i / p ) ) f(ip) = f(i) + p^2(f(i)-f(i/p)) f(ip)=f(i)+p2(f(i)f(i/p)),该公式更贴合线性筛求积性函数模板,且不需要额外的改动,运行时间略优于原有方法。

代码

#include <cstdio>
#define MAXN 1000005

using namespace std;

int prime[MAXN], v[MAXN], tot;
long long f[MAXN];

void init(int n) {
    f[1] = 1;
    for (int i = 2; i <= n; ++i) {
        if (!v[i]) {
            prime[++tot] = v[i] = i;
            f[i] = 1ll * i * i - i + 1;
            // f[i] = i * i - i + 1; This will WA.
        }
        for (int j = 1; j <= tot; ++j) {
            if (prime[j] > n / i) break;
            v[i*prime[j]] = prime[j];
            if (v[i] == prime[j]) {
                f[i*prime[j]] = f[i]+(f[i]-f[i/prime[j]])*prime[j]*prime[j];
                break;
            } else {
                f[i*prime[j]] = f[i] * f[prime[j]];
            }
        }
    }
}

int main() {
    init(MAXN - 5);
    int T;
    scanf("%d", &T);
    while (T--) {
        int n;
        scanf("%d", &n);
        printf("%lld\n", (f[n] + 1) * n / 2);
    }
    return 0;
}

CSDN 的 Markdown 做的不错,以后主要发这里了。

  • 37
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值