首先线性筛出phi()
然后枚举每个素数p,考虑p对答案的贡献:
gcd(i, j) = p <=> gcd(i / p, j / p) = 1
令x = i / p, y = j / p,再不妨x >= y,则
(1)x = y,只有x = y = 1
(2)x > y,x的个数就有phi(y)个
所以p对答案的贡献就是(2 * Σ phi(y)) - 1
故我们对phi()前缀和一下,再枚举质数p,直接计算就可以了
1 /************************************************************** 2 Problem: 2818 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:1076 ms 7 Memory:131664 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 13 using namespace std; 14 const int N = 10000005; 15 int n, tot; 16 int phi[N], p[N / 10]; 17 long long ans, sum[N]; 18 bool Flag[N]; 19 20 void get_phi(int N){ 21 memset(Flag, 0 , sizeof(Flag)); 22 phi[1] = 1; 23 int i, j, k; 24 for (i = 2; i <= N; ++i){ 25 if (!Flag[i]) 26 p[++tot] = i, phi[i] = i - 1; 27 for (j = 1; j <= tot; ++j){ 28 if ((k = i * p[j]) > N) break; 29 Flag[k] = 1; 30 if ( i % p[j] == 0){ 31 phi[k] = phi[i] * p[j]; 32 break; 33 } 34 phi[k] = phi[i] * (p[j] - 1); 35 } 36 } 37 } 38 39 int main(){ 40 scanf("%d", &n); 41 get_phi(n); 42 int i; 43 for (i = 1; i <= n; ++i) 44 sum[i] = sum[i - 1] + phi[i]; 45 for (i = 1; i <= tot; ++i) 46 ans += sum[n / p[i]] * 2 - 1; 47 printf("%lld\n", ans); 48 return 0; 49 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen