转载请注明出处,谢谢http://blog.youkuaiyun.com/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;
}