码迷,mamicode.com
首页 > 其他好文 > 详细

SPOJ LCMSUM - LCM Sum

时间:2018-09-21 19:04:16      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:typename   题意   template   i++   view   display   case   style   时间   

题意是求:

    $\sum_{i = 1}^{n}lcm(i, n)$

    $= \sum_{i = 1}^{n}\frac{ni}{gcd(i, n)}$

    $= n\sum_{i = 1}^{n}\frac{i}{gcd(i, n)}$

    $= n\sum_{d|n}\sum_{i = 1}^{n}d*[gcd(i, n)==d]$

    $= n\sum_{d|n}\sum_{i = 1}^{\frac{n}{d}}i*[gcd(i, \frac{n}{d})==1]$

    $= n\sum_{d|n}\sum_{i = 1}^{d}i*[gcd(i, d)==1]$

设$h(d) = \sum_{i = 1}^{d}i*[gcd(i, d)==1]$,其实是求在$1,2,3...d$的范围内与$d$互质的数的总和,当$d>1$时,它就等于$\frac{\phi (d) * d}{2}$

证明:

    因为$gcd(i, d) == 1$,那么也有$gcd(d - i, d) == 1$,所以假如$i$与$d$互质,那么$d - i$也与$d$互质,它们的和是$d$,也就是说在$1, 2, 3, ..., d$中,这样的数对一共有$\frac{\phi (d)}{2}$个,每一对的和是$d$,所以$h(d) = \frac{\phi (d) * d}{2}$

$h(1)$当然是等于$1$的。

这样我们线性筛出欧拉函数$\phi (i)$,然后再暴力算$h(i)$,最后询问的时候输出$h(n) * n$.

时间复杂度是$O(MaxNlogMaxN + T)$。

Code:

技术分享图片
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;

const int N = 1e6 + 5;
const int Maxn = 1e6;

int testCase, pCnt = 0, pri[N];
ll h[N], phi[N];
bool np[N];

template <typename T>
inline void read(T &X) {
    X = 0; char ch = 0; T op = 1;
    for(; ch > 9|| ch < 0; ch = getchar())
        if(ch == -) op = -1;
    for(; ch >= 0 && ch <= 9; ch = getchar())
        X = (X << 3) + (X << 1) + ch - 48;
    X *= op;
}

void sieve() {
    phi[1] = 1LL;
    for(int i = 2; i <= Maxn; i++) {
        if(!np[i]) pri[++pCnt] = i, phi[i] = i - 1;
        for(int j = 1; j <= pCnt && pri[j] * i <= Maxn; j++) {
            np[i * pri[j]] = 1;
            if(i % pri[j] == 0) {
                phi[i * pri[j]] = phi[i] * pri[j];
                break;
            }
            phi[i * pri[j]] = phi[i] * (pri[j] - 1);
        }
    }
    
    for(int i = 1; i <= Maxn; i++) {
        ll now = phi[i] * i / 2;
        if(i == 1) now = 1LL;
        for(int j = i; j <= Maxn; j += i)
            h[j] += now;
    }
}

int main() {
    sieve();
    for(read(testCase); testCase--; ) {
        int n; read(n);
        printf("%lld\n", 1LL * n * h[n]);
    }
    return 0;
}
View Code

 

SPOJ LCMSUM - LCM Sum

标签:typename   题意   template   i++   view   display   case   style   时间   

原文地址:https://www.cnblogs.com/CzxingcHen/p/9687956.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!