【SPOJ VLATTICE】Visible Lattice Points——莫比乌斯反演3

来源:互联网 发布:mysql pxc 架构 编辑:程序博客网 时间:2024/04/30 02:38

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 :
3
1
2
5

Sample Output :
7
19
175

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

题意:给你一个三维的地图,坐标为(0,0,0)(n,n,n),判断有多少个坐标与原点之间的连线不经过其他的点。
思路:不经过其他的点也就是gcd(x,y,z) = 1,所以题意就变成在[1,n]中有多少三元组(x,y,z)的gcd 等于1.
令g(n)表示n|gcd(x,y,z)的个数
f(n)表示gcd(x,y,z)等于n的个数,所以g(n)=n|df(d),所以f(n)=n|dμ(dn)g(d)
由于n=1所以ans=f(1)=d=1nμ(d)g(d)=d=1nμ(d)ndndnd
在计算的时候由于(0,0,1),(0,1,0),(1,0,0)不会被计算到所以初始答案为3,而在计算的过程中xoy,xoz,yoz的面不会计算到,所以在计算的时候也要加上。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <string>#include <vector> #include <algorithm>using namespace std;typedef long long LL;const int Max = 1000100;bool vis[Max];int prime[Max],cnt;int mu[Max];void GetMobius() {    memset(vis,false,sizeof(vis));    mu[1] = 1; cnt = 0;    for(int i = 2 ;i < Max; i++){        if(!vis[i]) {            prime[cnt++] = i;            mu[i] = -1;        }        for(int j = 0; j < cnt && i*prime[j] < Max ; j++) {            vis[i*prime[j]] = true;            if(i % prime[j]) mu[i*prime[j]] = -mu[i];            else {                mu[i*prime[j]] = 0;                break;            }        }    } }LL Cal(LL n){    int end;    LL ans =3;    for(int i = 1;i <= n; i ++){        ans+=mu[i]*(n/i)*(n/i)*(n/i+3);    }    return ans;}int main() {    int T,n;    GetMobius();    scanf("%d",&T);    while(T--) {        scanf("%d",&n);        LL ans = Cal(n);        printf("%lld\n",ans);    }    return 0;}
1 0
原创粉丝点击