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;
}