SPOJ GCDEX (数论)

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

题意:求sigma (gcd (i , j))  1 <= i < j <= n

和POJ 2480类似,如果枚举j,求的话,还是会TLE的。。。

考虑sigma(gcd (i , n)) = sigma (d * phi[n / d]) d | n。

做法同样是先预处理出phi,然后枚举gcd = d。

O(n)预处理,O(1)查询

 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <set>

#include <map>

#include <string>

#include <vector>

#include <queue>

#include <stack>

#define lowbit(x) (x & (-x))

#define Key_value ch[ch[root][1]][0] 

#pragma comment(linker, "/STACK:1024000000,1024000000")    

using namespace std;

typedef long long LL;

const int N = 1000005;

int phi[N];

LL ans[N];

void init () {

    for (int i = 2 ; i < N ; i ++) {

        if (phi[i]) continue;

        for (int j = i ; j < N ; j += i) {

            if (phi[j] == 0) phi[j] = j;

            phi[j] = phi[j] / i * (i - 1);

        }

    }

    for (int i = 2 ; i < N ; i ++)

        ans[i] = phi[i];

    for (int i = 2 ; i * i < N ; i ++) {

        ans[i * i] += 1LL * phi[i] * i;

        for (int j = i + 1 ; j * i < N ; j ++) {

            ans[j * i] += 1LL * phi[i] * j + 1LL * phi[j] * i;

        }

    }

    for (int i = 1 ; i < N ; i ++)

        ans[i] += ans[i - 1];

}

int main () {

    #ifndef ONLINE_JUDGE

        freopen ("input.txt" , "r" , stdin);

        // freopen ("output.txt" , "w" , stdout);

    #endif

    int n ;

    init ();

    while (cin >> n && n) {

        cout << ans[n] << endl;

    }

    return 0;

}


 

 

你可能感兴趣的:(poj)