题目描述
作为体育委员,C 君负责这次运动会仪仗队的训练。仪仗队是由学生组成的 N×N 的方阵,为了保证队伍在行进中整齐划一,C 君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。
现在,C 君希望你告诉他队伍整齐时能看到的学生人数。
输入格式
一行,一个正整数 NN。
输出格式
输出一行一个数,即 C 君应看到的学生人数。
输入输出样例
输入 #1复制
4
输出 #1复制
9
解题思路:
即对任意整点 (x,y) ,点 (λx,λy),(λ>1) 是看不到的
我们可以显然发现:gcd(λx,λy)=λgcd(x, y)>λ⋅1=λ>1
也就是说,对于一个点 (x,y) ,当gcd(x,y)=1 时这个点看不到
而对于任意满足 gcd(x,y)=1 的点 (x,y) ,若它会被遮挡,则必定有整点 ,(mx,my),(m>1) 存在
根据 gcd(x,y)=1 ,我们能发现这样的点不存在
所以我们得出结论:一个点 (x,y) 能被看到,当且仅当 gcd(x,y)=1
#include<bits/stdc++.h>
using namespace std;
const int N = 50000;
int vis[N];
int prime[N];
int phi[N];
int sum[N];
void get_phi() {
phi[1] = 1;
int cnt = 0;
for (int i = 2; i < N; i++) {
if (!vis[i]) {
vis[i] = i;
prime[cnt++] = i;
phi[i] = i - 1;
}
for (int j = 0; j < cnt; j++) {
if (i * prime[j] > N) break;
vis[i * prime[j]] = prime[j];
int m = i * prime[j];
if (i % prime[j] == 0) { // m = prime[i] * i * ````
phi[m] = phi[i] * prime[j];
break;
}
phi[m] = phi[i] * phi[prime[j]];
}
}
}
int main() {
get_phi();
sum[1] = 1;
for (int i = 2; i <= N; i++)
sum[i] = sum[i - 1] + phi[i];
int n;
cin >> n;
if (n == 1) cout << "0" << endl;
else {
printf("%d\n", 2 * sum[n - 1] + 1);
}
return 0;
}