题目链接
一个点可看见就是它和原点连线没有其他点存在。
我们把所有的有序三元组
(
x
,
y
,
z
)
(x,y,z)
(x,y,z)找出来,发现其中
g
c
d
(
x
,
y
,
z
)
gcd(x,y,z)
gcd(x,y,z)相等的有多个,然而只能取一个。
设
f
(
n
)
f(n)
f(n)为
gcd
(
x
,
y
,
z
)
=
n
\gcd(x,y,z)=n
gcd(x,y,z)=n的有序三元组个数,
g
(
n
)
g(n)
g(n)为
gcd
(
x
,
y
,
z
)
=
n
的
倍
数
\gcd(x,y,z)=n的倍数
gcd(x,y,z)=n的倍数的有序三元组个数,
那么有
g
(
n
)
=
∑
n
∣
d
f
(
d
)
=
⌊
N
n
⌋
3
g(n) = \sum_{n|d}f(d)={\left \lfloor \dfrac{N}{n}\right \rfloor }^3
g(n)=n∣d∑f(d)=⌊nN⌋3
所以
f
(
n
)
=
∑
n
∣
d
μ
(
d
)
g
(
d
n
)
\begin{aligned} f(n) &= \sum_{n|d}\mu(d)g\left(\dfrac{d}{n}\right)\\ \end{aligned}
f(n)=n∣d∑μ(d)g(nd)
我们求
f
(
1
)
f(1)
f(1),故
f
(
1
)
=
∑
d
=
1
N
μ
(
d
)
g
(
d
)
=
∑
d
=
1
N
μ
(
d
)
⌊
N
d
⌋
3
\begin{aligned} f(1) &= \sum_{d=1}^{N}\mu(d)g(d)\\ &=\sum_{d=1}^{N}\mu(d){\left \lfloor \dfrac{N}{d}\right \rfloor }^3 \end{aligned}
f(1)=d=1∑Nμ(d)g(d)=d=1∑Nμ(d)⌊dN⌋3
这里还要加上坐标轴上的三个点以及坐标平面上的点。
坐标平面上的点即为三维退化到二维,所以公式为
∑
d
=
1
N
μ
(
d
)
⌊
N
d
⌋
2
\sum_{d=1}^{N}\mu(d){\left \lfloor \dfrac{N}{d}\right \rfloor }^2
d=1∑Nμ(d)⌊dN⌋2
令
s
(
N
d
)
=
⌊
N
d
⌋
3
+
⌊
N
d
⌋
2
s\left(\dfrac{N}{d}\right)={\left \lfloor \dfrac{N}{d}\right \rfloor }^3 +{\left \lfloor \dfrac{N}{d}\right \rfloor }^2
s(dN)=⌊dN⌋3+⌊dN⌋2
则
a
n
s
=
∑
d
=
1
N
μ
(
d
)
s
(
N
d
)
+
3
ans = \sum_{d=1}^{N}\mu(d)s\left(\dfrac{N}{d}\right)+3
ans=d=1∑Nμ(d)s(dN)+3
数论分块解决,时间复杂度
O
(
n
+
T
n
)
O(n+T\sqrt{n})
O(n+Tn
)
#include<bits/stdc++.h> #define ll long long #define ull unsigned long long #define pii pair<int,int> using namespace std; const double eps = 1e-10; const double pi = acos(-1.0); const int maxn = 1e6 + 10; int t; ll p[maxn],mu[maxn]; int cnt; bool isp[maxn]; void getp(){ isp[1] = mu[1] = 1; for(int i = 2; i < maxn; i++){ if(!isp[i]) p[++cnt] = i,mu[i] = -1; for(int j = 1; j <= cnt && i*p[j] < maxn; j++){ isp[i*p[j]] = 1; if(i%p[j]) mu[i*p[j]] = -mu[i]; else break; } } for(int i = 1; i < maxn; i++) mu[i] = mu[i-1] + mu[i]; } inline ll s(ll a){ return a*a*(a+3); } void solve(){ getp(); scanf("%d",&t); while(t--){ ll n; scanf("%lld",&n); ll l = 1, r = 0; ll ans = 3; while(l <= n){ r = n/(n/l); ans += s(n/l)*(mu[r]-mu[l-1]); l = r+1; } printf("%lld\n",ans); } } int main() { solve(); return 0; }