题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=37161
题意:gcd(x, y) = 质数, 1 <= x, y <= n
的对数
思路:显然gcd(x, y) = k, 1 <= x, y <= n
的对数等于求(x, y) = 1, 1 <= x, y <= n/k
的对数。所以,枚举每个质数p
,然后求gcd(x, y) = 1, 1 <= x, y <= n/p
的个数。那么问题的关键就是怎么求gcd(x, y) = 1, 1 <= x, y <= n / pi,在[1, y]
和y
互质的数有phi(y)
个,如果我们令x < y
,那么答案就是sigma(phi(y))
。因为x, y
是等价的,所以答案*2,又因为(1, 1)
只有一对,所以-1。最终答案为sigma(sigma(phi(n/prime[i])) * 2 - 1)
。
code:
1 #include <cstdio> 2 #include <cstring> 3 typedef long long LL; 4 const int MAXN = 10000005; 5 6 LL phi[MAXN]; 7 int primes[MAXN]; 8 bool is[MAXN]; 9 int cnt; 10 11 12 void init(int n) 13 { 14 phi[1] = 1L; 15 cnt = 0; 16 memset(is, false, sizeof(is)); 17 for (int i = 2; i <= n; ++i) { 18 if (!is[i]) { 19 primes[cnt++] = i; 20 phi[i] = i - 1; 21 } 22 for (int j = 0; j < cnt && i * primes[j] <= n; ++j) { 23 is[i * primes[j]] = true; 24 if (i % primes[j] == 0) phi[i * primes[j]] = phi[i] * primes[j]; 25 else phi[i * primes[j]] = phi[i] * (primes[j] - 1); 26 } 27 } 28 } 29 30 int main() 31 { 32 int n; 33 while (scanf("%d", &n) != EOF) { 34 init(n); 35 LL ans = 0; 36 for (int i = 2; i <= n; ++i) phi[i] += phi[i - 1]; 37 for (int i = 0; i < cnt; ++i) { 38 ans += phi[n / primes[i]] * 2 - 1; 39 } 40 printf("%lld ", ans); 41 } 42 return 0; 43 }