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
题意:一个n*n*n的方格,从最左下角(0, 0, 0)最多可以看到多少个点?(不被遮挡)包括方格内部。
思路:这道题的话,我们先分析情况。假设能看到的点的坐标为则必须满足:。当时是不成立的。
(1)当中有两个为0时,只有三种情况;
(2)当中有一个为0时,相当于求的对数;
(3)当均大于0时,相当于求的对数。
结合以上三个情况,我们可以得出式子: 。
令
再记:
则F(x)为
再有
据莫比乌斯反演
∴
同理
将两个式子合并得到最终得到
由于还需要加上三条坐标轴,所以:
思路上有一部分借鉴:https://blog.csdn.net/baiyifeifei/article/details/82954002
AC代码:
#include <stdio.h>
#include <string>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
typedef long long ll;
const int maxx=1000010;
const int mod=10007;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
using namespace std;
ll mu[maxx],prime[maxx];
bool vis[maxx];
ll cnt;
void get_mu()
{
memset(prime,0,sizeof(prime));
memset(vis,false,sizeof(vis));
memset(mu,0,sizeof(mu));
cnt=0;
mu[1]=1;
for(int i=2; i<=maxx; i++)
{
if(!vis[i])
{
prime[cnt++]=i;
mu[i]=-1;
}
for(int j=0; j<cnt && i*prime[j]<=maxx; j++)
{
vis[i*prime[j]]=true;
if(i%prime[j])
{
mu[i*prime[j]]=-mu[i];
}
else
{
mu[i*prime[j]]=0;
break;
}
}
}
}
int main()
{
get_mu();
int t;
scanf("%d",&t);
while(t--)
{
ll n;
scanf("%lld",&n);
ll ans=3;
for(ll i=1; i<=n; i++)
ans+=mu[i]*(n/i)*(n/i)*(n/i+3);
printf("%lld\n",ans);
}
return 0;
}