「Luogu P2398」GCD SUM「莫比乌斯反演」

版权声明:本文为hzy原创文章,未经博主允许不可随意转载。 https://blog.csdn.net/Binary_Heap/article/details/81979908

题目传送门

题意

i = 1 n j = 1 n g c d ( i , j ) n <= 10 5

题解

i = 1 n j = 1 n g c d ( i , j )

= d = 1 n i = 1 n j = 1 n [ g c d ( i , j ) = d ]

= d = 1 n d i = 1 n d j = 1 n d [ g c d ( i , j ) = 1 ]

= d = 1 n d i = 1 n d j = 1 n d e ( g c d ( i , j ) )

= d = 1 n d i = 1 n d j = 1 n d d | g c d ( i , j ) μ ( d )

= d = 1 n d i = 1 n d j = 1 n d d | i , d | j μ ( d )

= d = 1 n d d = 1 n μ ( d ) i = 1 , d | i n d j = 1 , d | j n d 1

= d = 1 n d d = 1 n μ ( d ) i = 1 n d d j = 1 n d d 1

= d = 1 n d = 1 n i d ( d ) μ ( d ) n d d n d d

= k = 1 n d = 1 n i d ( d ) μ ( k d ) n k n k

= k = 1 n ( i d μ ) ( k ) n k n k

= k = 1 n ϕ ( k ) n k n k

然后可以线性筛 O ( n ) 预处理 ϕ ,然后通过数论分块 O ( n ) 计算答案.

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

typedef long long LL;

const int MAXN = 100100;

bool tag[MAXN];
int n, pr[MAXN], cnt, phi[MAXN];
LL phis[MAXN], ans;

void sieve(int n) { //线性筛模版 
    memset(tag, 1, sizeof tag); tag[1] = false;
    phi[1] = phis[1] = 1;
    for(int i = 2; i <= n; i ++) {
        if(tag[i]) {
            pr[++ cnt] = i;
            phi[i] = i - 1;
        }
        for(int j = 1; j <= cnt && i * pr[j] <= n; j ++) {
            tag[i * pr[j]] = false;
            if(i % pr[j] == 0) {
                phi[i * pr[j]] = phi[i] * pr[j];
                break ;
            }
            phi[i * pr[j]] = phi[i] * (pr[j] - 1);
        }
        phis[i] = phis[i - 1] + phi[i]; //phis为欧拉函数的前缀和. 
    }
}

int main() {
    scanf("%d", &n);
    sieve(n);
    for(int i = 1, j; i <= n; i = j + 1) {
        j = n / (n / i); //j为当前块的右端点,i为左端点 
        ans += (n / i) * 1ll * (n / i) * (phis[j] - phis[i - 1]);
    }
    printf("%lld\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Binary_Heap/article/details/81979908
今日推荐