【题解&杜教筛总结】51Nod1238 最小公倍数和V3

前置知识:杜教筛。(不会点这里)。

大片公式预警!!!

题意

∑ i = 1 n ∑ j = 1 n lcm ( i , j ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\text{lcm}(i,j) i=1nj=1nlcm(i,j)。( 1 ≤ n ≤ 1 0 10 1\leq n\leq 10^{10} 1n1010

题解

简单回顾

开始之前,先来回顾一下几个和杜教筛有关的式子(定义 ∗ * 为数论函数的狄利克雷卷积):
I ( n ) = 1 , i d ( n ) = n , ϵ ( n ) = [ n = 1 ] μ ∗ I = ϵ ( 1 ) φ ∗ I = i d ( 2 ) μ ∗ i d = φ ( 3 ) \begin{aligned}&I(n)=1, \quad id(n)=n, \quad\epsilon(n)=[n=1]\\&\mu*I=\epsilon \qquad (1) \\&\varphi*I=id \qquad (2)\\&\mu*id=\varphi \qquad (3)\\\end{aligned} I(n)=1,id(n)=n,ϵ(n)=[n=1]μI=ϵ(1)φI=id(2)μid=φ(3)
( 1 ) (1) (1)可以推出 ∑ d ∣ n μ ( d ) = [ n = 1 ] \sum\limits_{d|n}\mu(d)=[n=1] dnμ(d)=[n=1]

( 2 ) (2) (2)可以推出 ∑ d ∣ n φ ( d ) = n \sum\limits_{d|n}\varphi(d)=n dnφ(d)=n

( 3 ) (3) (3)则经常用于 μ \mu μ φ \varphi φ的互相转化。

正式开始

看到这种题,上来就先暴力化式子。(除法默认下去整)
∑ i = 1 n ∑ j = 1 n lcm ( i , j ) = ∑ i = 1 n ∑ j = 1 n i j ( i , j ) = ∑ d = 1 n 1 d ∑ i = 1 n d ∑ j = 1 n d d 2 i j ⋅ [ ( i , j ) = d ] (先枚举gcd) = ∑ d = 1 n d ∑ i = 1 n d ∑ j = 1 n d i j ∑ x ∣ ( i , j ) μ ( x ) (由(1)式可得) = ∑ d = 1 n d ∑ x = 1 n d x 2 μ ( x ) ∑ i = 1 n d x ∑ j = 1 n d x i j \begin{aligned}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\text{lcm}(i,j)&=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\frac{ij}{(i,j)} \\&=\sum_{d=1}^{n}\frac{1}{d}\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}d^2ij\cdot[(i,j)=d] &\text{(先枚举gcd)}\\&=\sum_{d=1}^{n}d\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}ij\sum_{x|(i,j)}\mu(x) &\text{(由(1)式可得)}\\&=\sum_{d=1}^{n}d \sum_{x=1}^\frac{n}{d}x^2\mu(x) \sum_{i=1}^{\frac{n}{dx}}\sum_{j=1}^{\frac{n}{dx}}ij\end{aligned} i=1nj=1nlcm(i,j)=i=1nj=1n(i,j)ij=d=1nd1i=1dnj=1dnd2ij[(i,j)=d]=d=1ndi=1dnj=1dnijx(i,j)μ(x)=d=1ndx=1dnx2μ(x)i=1dxnj=1dxnij(先枚举gcd((1)式可得)
接下来,设 T = d x T=dx T=dx g ( x ) = ∑ i = 1 x ∑ j = 1 x i j = ( ∑ i = 1 x i ) 2 = n 2 ( n + 1 ) 2 4 g(x)=\sum\limits_{i=1}^{x}\sum\limits_{j=1}^{x}ij=(\sum\limits_{i=1}^{x}i)^2=\frac{n^2(n+1)^2}{4} g(x)=i=1xj=1xij=(i=1xi)2=4n2(n+1)2。于是我们先枚举 T T T,把 g ( x ) g(x) g(x)带进去,就可以接着化上面那个式子了。
∑ d = 1 n d ∑ x = 1 n d x 2 μ ( x ) ∑ i = 1 n d x ∑ j = 1 n d x i j = ∑ T = 1 n g ( n T ) ∑ x ∣ T x 2 μ ( x ) ⋅ T x \begin{aligned}\sum_{d=1}^{n}d \sum_{x=1}^\frac{n}{d}x^2\mu(x) \sum_{i=1}^{\frac{n}{dx}}\sum_{j=1}^{\frac{n}{dx}}ij&=\sum_{T=1}^{n}g(\frac{n}{T})\sum_{x|T}x^2\mu(x)\cdot\frac{T}{x}\end{aligned} d=1ndx=1dnx2μ(x)i=1dxnj=1dxnij=T=1ng(Tn)xTx2μ(x)xT
然后我们发现前面 g ( n T ) g(\frac{n}{T}) g(Tn)可以除法分块,关键在于如何求出后面这一部分的前缀和。

所以令 F ( n ) = ∑ x ∣ n x 2 μ ( x ) ⋅ n x F(n)=\sum\limits_{x|n}x^2\mu(x)\cdot\frac{n}{x} F(n)=xnx2μ(x)xn A ( n ) = n 2 μ ( n ) A(n)=n^2\mu(n) A(n)=n2μ(n) B ( n ) = n B(n)=n B(n)=n,那么 F = A ∗ B F=A*B F=AB

B B B看起来已经很简单了,所以我们尝试用构造一个 C C C,让 A ∗ C A*C AC变得简单一些,这样就可以用杜教筛求前缀和了(很明显 F F F是积性函数)。

我们发现 A A A中的 x 2 x^2 x2让我们很不舒服,所以我们考虑 C ( x ) = x 2 C(x)=x^2 C(x)=x2,这样在卷积的时候可以把 x 2 x^2 x2给消掉。
( A ∗ C ) ( n ) = ∑ x ∣ n x 2 μ ( x ) ( n x ) 2 = n 2 ∑ x ∣ n μ ( x ) = n 2 [ n = 1 ] (由之前的推论可得) = [ n = 1 ] ∴ A ∗ C = ϵ \begin{aligned}(A*C)(n)&=\sum_{x|n}x^2\mu(x)(\frac{n}{x})^2\\&=n^2\sum_{x|n}\mu(x)\\&=n^2[n=1] &\text{(由之前的推论可得)}\\&=[n=1]\\\therefore A*C=\epsilon\end{aligned} (AC)(n)AC=ϵ=xnx2μ(x)(xn)2=n2xnμ(x)=n2[n=1]=[n=1](由之前的推论可得)
诶,这下看起来简单多了。
∴ F ∗ C = ( A ∗ C ) ∗ B = ϵ ∗ B = B ∴ ( F ∗ C ) ( n ) = n \begin{aligned}\therefore F*C&=(A*C)*B\\&=\epsilon*B\\&=B\\\therefore (F*C)&(n)=n\end{aligned} FC(FC)=(AC)B=ϵB=B(n)=n
S ( n ) S(n) S(n) F ( n ) F(n) F(n)的前缀和,然后套上杜教筛的式子:
C ( 1 ) S ( n ) = ∑ i = 1 n ( F ∗ C ) ( n ) − ∑ i = 2 n C ( i ) S ( n i ) 即 S ( n ) = n ( n + 1 ) 2 − ∑ i = 2 n i 2 S ( n i ) \begin{aligned}C(1)S(n)&=\sum_{i=1}^n(F*C)(n)-\sum_{i=2}^nC(i)S(\frac{n}{i})\\即\quad S(n)&=\frac{n(n+1)}{2}-\sum_{i=2}^{n}i^2S(\frac{n}{i})\end{aligned} C(1)S(n)S(n)=i=1n(FC)(n)i=2nC(i)S(in)=2n(n+1)i=2ni2S(in)
那么只要能够线性求出前几百万个 S S S就可以直接杜教筛了。

观察 F ( n ) = ∑ x ∣ n x 2 μ ( x ) ⋅ n x = n ∑ x ∣ n x μ ( x ) F(n)=\sum\limits_{x|n}x^2\mu(x)\cdot\frac{n}{x}=n\sum\limits_{x|n}x\mu(x) F(n)=xnx2μ(x)xn=nxnxμ(x),所以考虑线性筛出积性函数 g ( n ) = ∑ x ∣ n x μ ( x ) g(n)=\sum\limits_{x|n}x\mu(x) g(n)=xnxμ(x)

我们想想线性筛的时候有那些情况需要考虑。

  1. n n n为质数时, g ( n ) = 1 ⋅ μ ( 1 ) + n ⋅ μ ( n ) = 1 − n g(n)=1\cdot \mu(1)+n\cdot \mu(n)=1-n g(n)=1μ(1)+nμ(n)=1n
  2. p p p为质数且与 i i i互质时, g ( i ⋅ p ) = g ( i ) ⋅ g ( p ) = g ( i ) ⋅ ( 1 − p ) g(i\cdot p)=g(i)\cdot g(p)=g(i)\cdot (1-p) g(ip)=g(i)g(p)=g(i)(1p)
  3. p p p为质数且 i i i为p的倍数时,由积性函数的性质可知, g ( i ) = g ( p 1 a 1 ) ⋅ g ( p 2 a 2 ) ⋯ g(i)=g(p_1^{a_1})\cdot g(p_2^{a_2})\cdots g(i)=g(p1a1)g(p2a2),那么 g ( i ⋅ p ) g(i\cdot p) g(ip)中, p p p的指数至少是2,又因为当指数 a > 1 a>1 a>1 g ( p a ) = g ( p a − 1 ) + p a ⋅ μ ( p a ) = g ( p a − 1 ) g(p^a)=g(p^{a-1})+p^a\cdot \mu(p^a)=g(p^{a-1}) g(pa)=g(pa1)+paμ(pa)=g(pa1),则 g ( p a ) = g ( p ) g(p^{a})=g(p) g(pa)=g(p),所以此时 g ( i ⋅ p ) = g ( i ) g(i\cdot p)=g(i) g(ip)=g(i)

考虑完这三种情况后,我们就可以线性筛出 S S S了。

代码

#include 
#define ll long long
#define MAX 5000005
#define P 1000000007
using namespace std;

ll qpow(ll a, ll n){
    ll res = 1;
    while(n){
        if(n&1) res = res*a%P;
        a = a*a%P;
        n >>= 1;
    }
    return res;
}

const ll inv2 = (P+1)/2, inv6 = 166666668;

int cnt;
ll p[MAX], vis[MAX], f[MAX];
void init(int n){
    f[1] = 1;
    for(int i = 2; i <= n; i++){
        if(!vis[i]){
            p[++cnt] = i;
            f[i] = 1-i+P;
        }
        for(int j = 1; j <= cnt && p[j]*i <= n; j++){
            vis[p[j]*i] = 1;
            if(i%p[j] == 0){
                f[i*p[j]] = f[i];
                break;
            }
            f[i*p[j]] = f[i]*(1-p[j]+P)%P;
        }
    }
    for(int i = 1; i <= n; i++){
        f[i] = (f[i]*i%P+f[i-1])%P;
    }
}

ll sum(ll n){
    n %= P;
    return n*(n+1)%P*(2*n%P+1)%P*inv6%P;
}
ll g(ll n){
    n %= P;
    return n*(n+1)%P*n%P*(n+1)%P*inv2%P*inv2%P;
}

map<ll, ll> s;
ll S(ll n){
    if(n < MAX) return f[n];
    if(s.count(n)) return s[n];
    ll ans = (n+1)%P*(n%P)%P*inv2%P;
    for(ll l = 2, r; l <= n; l = r+1){
        r = n/(n/l);
        (ans -= (sum(r)-sum(l-1)+P)%P*S(n/l)%P) %= P;
        if(ans < 0) ans += P;
    }
    return s[n] = ans%P;
}

int main()
{
    init(MAX-1);
    ll n, ans = 0;
    cin >> n;
    for(ll l = 1, r; l <= n; l = r+1){
        r = n/(n/l);
        ll t = n/l, sum = (S(r)-S(l-1)+P)%P;
        ans = (ans+g(t)%P*sum%P)%P;
    }
    cout << ans << endl;

    return 0;
}

你可能感兴趣的:(题解,模板)