SP3871 GCDEX - GCD Extreme

Posted gzygzy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SP3871 GCDEX - GCD Extreme相关的知识,希望对你有一定的参考价值。

SP3871 GCDEX - GCD Extreme

题目让我们求
[sum_{i=1}^nsum_{j=i+1}^{n}gcd(i,j)]
[sum_{i=1}^nsum_{j=1}^{i-1}gcd(i,j)]
(g(n) = sum_{i=1}^{n-1}gcd(i,n))
[sum_{i=1}^ng(i)]
考虑如何快速求(g)
[g(n)=sum_{i=1}^{n-1}gcd(i,n)]
(gcd(i,n)==d)
换个方向枚举
[g(n)=sum_{d=1}^{n-1}dsum_{i=1}^n[gcd(i,n) == d]]
[g(n)=sum_{d=1}^{n-1}dsum_{i=1}^n[gcd(i,n) == d]]
[g(n)=sum_{d=1}^{n-1}dsum_{i=1}^{frac nd}[gcd(i,frac nd) == 1]]
[g(n)=sum_{d=1}^{n-1}dphi(frac nd)]

然后筛一下g(n),直接前缀和O(1)询查
怎么筛:枚举因子d,然后直接暴力+d,这就是著名的调和级数

    rep(i , 1, N){
        for(int j = 2 * i;j <= N;j += i) 
            g[j] += i * phi[j / i];
    }

AC代码:

#include <iostream>
#include <cstdio>
#define rep(i , x, p) for(register int i = x;i <= p;++ i)
#define gc getchar()
#define pc putchar
#define ll long long
const int maxN = 1e7 + 7;

int num , prime[maxN], phi[maxN];
bool is_prime[maxN];
ll sum[maxN] , g[maxN];

inline void init() {
    int N = 1000000;
    phi[1] = 1;
    rep(i , 2, N) {
        if(!is_prime[i]) prime[++ num] = i , phi[i] = i - 1;
        for(register int j = 1;j <= num && i * prime[j] <= N;++ j) {
            is_prime[i * prime[j]] = true;
            if(i % prime[j] == 0) {
                phi[i * prime[j]] = phi[i] * prime[j];
                break;
            }
            phi[i * prime[j]] = phi[i] * ( prime[j] - 1 );
        }
    }
    rep(i , 1, N){
        for(int j = 2 * i;j <= N;j += i) 
            g[j] += i * phi[j / i];
    }
    rep(i , 1, N) sum[i] = sum[i - 1] + g[i];
}

int main() {
    int n;
    init();
    while(scanf("%d",&n) == 1 && n) {
        printf("%lld
",sum[n]);    
    }
    return 0;
}













以上是关于SP3871 GCDEX - GCD Extreme的主要内容,如果未能解决你的问题,请参考以下文章

SP5971 LCMSUM

SP5971 LCMSUM 数论

Git (gnome-ssh-askpass:3871): Gtk-WARNING **: cannot open display:

P3871 [TJOI2010]中位数

如何将 const void* 强制转换为结构元素?

[置顶]模板速度