可以参考:https://wenku.baidu.com/view/fbe263d384254b35eefd34eb.html
求在(0,0,0)可以看到哪些点,xyz三个轴上各一个,然后在坐标系内的点,设坐标为(x,y,z), 1<=x,y,z<=N,在这个范围内,求有多少x,y,z,使gcd(x,y,z)=1
设
f(i)=[gcd(x,y,z)=i]
的(x,y,z)的个数,
,
F(i)=i|gcd(x,y,z)
的(x,y,z)的个数,
显然
F(i)=⌊xi⌋⌊yi⌋⌊zi⌋
,
,则
f(i)=∑i|du(di)F(d)=∑i|du(di)⌊xd⌋⌊yd⌋⌊zd⌋
这是空间内的,然后再求三个面上的
f(i)=[gcd(x,y)=i]
F[i]=i|gcd(x,y)
f(i)=∑i|du(di)F(d)=∑i|du(di)⌊xd⌋⌊yd⌋
然后一块加起来。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 1000005;
bool check[MAXN+10];
int prime[MAXN+10];
int mu[MAXN+10];
template <typename T>
T MIN(T a, T b, T c)
{
return min(a,min(b,c));
}
void Mobius()
{
memset(check,0,sizeof(check));
mu[1] = 1;
int tot = 0;
for(int i = 2; i <= MAXN; ++i)
{
if(!check[i])
{
mu[i] = -1;
prime[tot++] = i;
}
for(int 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 sum[MAXN+10];
int N;
LL solveOne(int a, int b, int c)
{
int limit = MIN(a,b,c);
LL res = 0;
for(int i = 1, la = 0; i <= limit; i = la +1)
{
la = MIN(a/(a/i),b/(b/i),c/(c/i));
res += (LL)(sum[la]-sum[i-1])*(a/i)*(b/i)*(c/i);
}
return res;
}
LL solveTwo(int a, int b)
{
int limit = min(a,b);
LL res = 0;
for(int i = 1, la = 0; i <= limit; i = la+1)
{
la = min(a/(a/i),b/(b/i));
res += (LL)(sum[la]-sum[i-1])*(a/i)*(b/i);
}
return res;
}
int main()
{
Mobius();
for(int i = 1; i <= MAXN; ++i)
sum[i] = sum[i-1]+mu[i];
int T;
LL res;
scanf("%d",&T);
while(T--)
{
res = 3LL;
scanf("%d",&N);
res += solveOne(N,N,N);
res += solveTwo(N,N)*3LL;
printf("%lld\n",res);
}
return 0;
}