原题题面:Visible Lattice Points
思路:
分析题面,可以发现,其中给出的
n
n
n,在平面直角坐标系上,由点
(
x
,
y
)
∈
[
0
,
n
]
(x, y) \in[0, n]
(x,y)∈[0,n] 围城的平面图形是一个正方形。由此可以看出
(
0
,
0
)
(0, 0)
(0,0)、
(
0
,
1
)
(0, 1)
(0,1) 和
(
1
,
1
)
(1, 1)
(1,1) 是必然可以被看到的,排除这三点之后,边界的情况就可以忽略了。
而其他点能被发现,(即不会与除自己以外的点与原点构成的线段撞车),当且仅当
1
≤
x
,
y
≤
n
1\leq x, y\leq n
1≤x,y≤n ,
x
≠
y
x\ne y
x=y ,and
g
c
d
(
x
,
y
)
=
1
gcd(x, y) = 1
gcd(x,y)=1(即
x
x
x 与
y
y
y 互质),由此,我们不难想到要利用欧拉函数。
可以发现,以函数
y
=
x
y=x
y=x为分界线,上下两部分的点是对称的,于是我们只要考虑其中的一部分就行。以下半部分为例,我们要考虑对于
∀
y
∈
[
2
,
n
]
,
(
y
∈
N
∗
)
\forall y\in[2, n],(y \in N*)
∀y∈[2,n],(y∈N∗) ,有多少个
x
x
x 是满足当
1
≤
x
<
y
1\leq x<y
1≤x<y 时,
x
x
x 与
y
y
y 互质,而这些数量恰好为
Φ
(
y
)
\Phi(y)
Φ(y)。
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e3 + 10;
int primes[N], cnt;
bool st[N];
int phi[N];
//筛法求欧拉函数
void eulers(int n)
{
for(int i = 2; i <= n; i++)
{
if(!st[i])
{
primes[cnt ++] = i;
phi[i] = i - 1;
}
for(int j = 0; primes[j] <= n / i; j++)
{
st[i * primes[j]] = true;
phi[primes[j] * i] = phi[i] * (i % primes[j] ? primes[j] - 1 : primes[j]);
if(i % primes[j] == 0) break;
}
}
}
int main()
{
int t;
cin >> t;
eulers(N);
for(int i = 1; i <= t; i++)
{
int n;
cin >> n;
LL count = 0;
for(int i = 2; i <= n; i++) count += phi[i];
cout << i << " " << n << " " << 2 * count + 3 << endl;
}
return 0;
}