转载请注明出处,谢谢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; }