您的位置:首页 > 其它

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

2017-08-15 10:48 369 查看
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

题意:问你在(0,0,0)点能看到n*n*n的正方体里的多少个点,一个点(x,y,z)能被看到,就是(0,0,0)与这个点的连线上没有其他的点,换句话说,就是gcd(x,y,z) == 1 。

这题是 bzoj2005 的升级版,从二维变成了三维,而且还有不同的是这题需要计算坐标轴上的点。

我们用莫比乌斯反演分别求出三个点都不是零的答案,有一个点是零的答案,还有就是在坐标轴上的点,有两个点是零的答案,加起来就是要求的点数了。

我们同样是设F(n) 为gcd是n的倍数的个数,f(n)为gcd是n的个数,

用莫比乌斯反演求出
f(1)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;

const int maxn = 1e6 + 10;
int p[maxn/10];
int flag[maxn];
int mu[maxn];
int cnt = 0;
void init()
{
int i,j;
mu[1] = 1;
for(i=2;i<maxn;i++)
{
if(!flag[i])
{
p[cnt++] = i;
mu[i] = -1;
}
for(j=0;j<cnt&&p[j]*i<maxn;j++)
{
flag[p[j]*i] = 1;
if(i % p[j] == 0)
{
mu[p[j]*i] = 0;
break;
}
mu[p[j]*i] = -mu[i];
}
}
}

int main(void)
{
int T,n,i,j;
init();
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
LL sum1 = 0;
LL sum2= 0;
for(i=1;i<=n;i++)
{
sum1 += (LL)mu[i]*(n/i)*(n/i)*(n/i);
sum2 += (LL)mu[i]*(n/i)*(n/i);
}
LL ans = sum1 + sum2*3 + 3;
printf("%lld\n",ans);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: