首页 > 代码库 > SPOJ7001(SummerTrainingDay04-N 莫比乌斯反演)

SPOJ7001(SummerTrainingDay04-N 莫比乌斯反演)

Visible Lattice Points 

Consider a N*N*N lattice. One corner is at (0,0,0) and the opposite one is at (N,N,N). How many lattice points are visible from corner at (0,0,0) ? A point X is visible from point Y iff no other lattice point lies on the segment joining X and Y. 
 
Input
The first line contains the number of test cases T. The next T lines contain an interger N 
 
Output
Output T lines, one corresponding to each test case. 
 
Sample Input : 




 
Sample Output : 

19 
175 
 
Constraints : 
T <= 50 
1 <= N <= 1000000

 

 1 //2017-08-04
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 
 9 const int N = 1000010;
10 int mu[N], prime[N], tot, phi[N];
11 long long plane[N];
12 bool book[N];
13 
14 void Moblus()//求出莫比乌斯函数
15 {
16     memset(book,false,sizeof(book));
17     mu[1] = 1;
18     int tot = 0;
19     for(int i = 2; i <= N; i++){
20         if(!book[i]){
21             prime[tot++] = i;
22             mu[i] = -1;
23         }
24         for(int j = 0; j < tot; j++){
25             if(i * prime[j] > N) break;
26             book[i * prime[j]] = true;
27             if( i % prime[j] == 0){
28                 mu[i * prime[j]] = 0;
29                 break;
30             }else{
31                 mu[i * prime[j]] = -mu[i];
32             }
33         }
34     }
35 }
36 
37 void getphi()    
38 {    
39    int i,j;    
40    phi[1]=1;    
41    for(i=2;i<=N;i++)//相当于分解质因式的逆过程    
42    {    
43        if(!book[i])
44        {    
45             prime[++tot]=i;//筛素数的时候首先会判断i是否是素数。    
46             phi[i]=i-1;//当 i 是素数时 phi[i]=i-1    
47         }    
48        for(j=1;j<=tot;j++)    
49        {    
50           if(i*prime[j]>N)  break;    
51           book[i*prime[j]]=1;//确定i*prime[j]不是素数    
52           if(i%prime[j]==0)//接着我们会看prime[j]是否是i的约数    
53           {    
54              phi[i*prime[j]]=phi[i]*prime[j];break;    
55           }    
56           else  phi[i*prime[j]]=phi[i]*(prime[j]-1);//其实这里prime[j]-1就是phi[prime[j]],利用了欧拉函数的积性    
57        }    
58    }    
59 }
60 
61 int main()
62 {
63     int T, n;
64     scanf("%d", &T);
65     Moblus();
66     getphi();
67     plane[2] = 1;
68     for(int i = 3; i < N; i++){
69         plane[i] = plane[i-1]+phi[i];
70     }
71     while(T--){
72         scanf("%d", &n);
73         long long ans = 3;
74         for(int d = 1; d <= n; d++){
75             int tmp = (int)(n/d);
76             ans += (long long)mu[d]*tmp*tmp*tmp;
77         }
78         ans += 3*(plane[n]*2+1);
79         printf("%lld\n", ans);
80     }
81 
82     return 0;
83 }

 

SPOJ7001(SummerTrainingDay04-N 莫比乌斯反演)