SPOJ 7001 VLATTICE - Visible Lattice Points(莫比乌斯反演)

题目链接:http://www.spoj.com/problems/VLATTICE/

题意:求gcd(a, b, c) = 1    a,b,c <=N 的对数。

思路:我们令函数g(x)为gcd(a, b, c) = x的对数,那么这题就是要求g(1)。我们令f(x)为x | gcd(a, b, c)的对数,显然f(n) = sigma(n | d, g(d)) 。f(d) = (n/d) * (n/d) * (n/d),那么我们就可以用莫比乌斯反演公式了, g(n) = sigma(n | d, mu(d/n)f(d))   g(1) = mu(d)f(d) = mu(d)*(n/d)*(n/d)*(n/d)。考虑1位为0,2位为0的情况。

莫比乌斯反演的两种形式:

g(n) = sigma(d | n, f(d))   f(n) = sigma(d | n, mu(d) * g(n/d))

g(n) = sigma(n | d, f(d))   f(n) = sigma(n | d, mu(d / n) * g(d))

code:

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 typedef long long LL;
 5 const int MAXN = 1000005;
 6 bool check[MAXN];
 7 int primes[MAXN];
 8 int mu[MAXN];
 9 
10 void moblus()
11 {
12     memset(check, false, sizeof(check));
13     mu[1] = 1;
14     int cnt = 0;
15     for (int i = 2; i < MAXN; ++i) {
16         if (!check[i]) {
17             primes[cnt++] = i;
18             mu[i] = -1;
19         }
20         for (int j = 0; j < cnt; ++j) {
21             if (i * primes[j] > MAXN) break;
22             check[i * primes[j]] = true;
23             if (i % primes[j] == 0) {
24                 mu[i * primes[j]] = 0;
25                 break;
26             } else {
27                 mu[i * primes[j]] = -mu[i];
28             }
29         }
30     }
31 }
32 
33 int main()
34 {
35     moblus();
36     int nCase;
37     scanf("%d", &nCase);
38     while (nCase--) {
39         int n;
40         scanf("%d", &n);
41         LL ans = 3;        // 001 010 100
42         for (int i = 1; i <= n; ++i) {
43             ans += (LL)mu[i] * (n / i) * (n / i) * (n / i + 3);
44         }
45         printf("%lld\n", ans);
46     }
47     return 0;
48 }

 

posted @ 2015-09-08 20:50  jasaiq  阅读(232)  评论(0编辑  收藏  举报