VLATTICE - 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 :
3
1
2
5
Sample Output :
7
19
175
Constraints :
T <= 50
1 <= N <= 1000000
思路:若(x,y,z)点可视,则gcd(x,y,z)=1,于是可用莫比乌斯函数解决之,因为若gcd不为1,则这个点被(x/gcd(x,y,z), y/gcd(x,y,z), z/gcd(x,y,z))挡住了,然后在面上和在棱上的点另外讨论,面上的当二元组求,加上棱上的只有3个点。这里可使用分块加速优化(n/i的值很多都是一样的,为了避免重复计算,可以一次性求出n/i相同的值,因此莫比乌斯数组改为前缀和)。
# include <iostream>
# include <cstdio>
# include <cstring>
# define ll long long
# define maxn 1000000
using namespace std;
short mu[maxn+3];
bool bo[maxn+3];
int prime[maxn+3];
int n;
void get_table()
{
mu[1] = 1;
memset(bo, 0, sizeof(bo));
for(int i=2; i<=maxn; ++i)
{
if(!bo[i])
{
prime[++prime[0]] = i;
mu[i] = -1;
}
for(int j=1; j<=prime[0] && i*prime[j]<=maxn; ++j)
{
bo[i*prime[j]] = 1;
if(i%prime[j]==0)
{
mu[i*prime[j]] = 0;
break;
}
else
mu[i*prime[j]] = -mu[i];
}
}
for(int i=1; i<=maxn; ++i)//分块加速。
mu[i] += mu[i-1];
}
void solve()
{
ll ans=0;
for(int i=1, j; i<=n; i=j+1)
{
j = n/(n/i);
ans += (ll)(mu[j]-mu[i-1])*(n/i)*(n/i)*(n/i+3);
}
printf("%lld\n",ans+3);
}
int main()
{
get_table();
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
solve();
}
return 0;
}