Visible Lattice Points SPOJ - 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
对题意进行简单的转化就会发现题目求的是
(在三个坐标面上,和在空间中)
令
再有
据莫比乌斯反演
∴
同理
将两个式子合并得到最终得到
由于还需要加上三条坐标轴,所以:
AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const long long MAXN=1e6+5;
//线性筛法求莫比乌斯函数
bool check[MAXN+10];
long long prime[MAXN+10];
int mu[MAXN+10];
void Moblus()
{
memset(check,false,sizeof(check));
mu[1] = 1;
long long tot = 0;
for(long long i = 2; i <= MAXN; i++)
{
if( !check[i] ){
prime[tot++] = i;
mu[i] = -1;
}
for(long long j = 0; j < tot; j++)
{
if(i * prime[j] > MAXN) break;
check[i * prime[j]] = true;
if( i % prime[j] == 0){
mu[i * prime[j]] = 0;
break;
}else{
mu[i * prime[j]] = -mu[i];
}
}
}
}
int main()
{
Moblus();
int t;
scanf("%d",&t);
while(t--)
{
long long n;
scanf("%lld",&n);
long long ans=3;
for(long long i=1;i<=n;i++) ans+=mu[i]*(n/i)*(n/i)*(n/i+3);
printf("%lld\n",ans);
}
}