BZOJ 2818 GCD(欧拉函数)

题目链接: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\n", ans);
41     }
42     return 0;
43 }
posted @ 2015-09-08 14:52  jasaiq  阅读(213)  评论(0编辑  收藏  举报