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;
}


你可能感兴趣的:(SPOJ GCDEX (数论))