题目描述
作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。
现在,C君希望你告诉他队伍整齐时能看到的学生人数。
输入输出格式
输入格式:
共一个数 N
输出格式:
共一个数,即C君应看到的学生人数。
输入输出样例
说明
【数据规模和约定】
对于 100% 的数据,1 ≤ N ≤ 40000
思路:
从图中可以很明显看出,原点只能看到斜率相同的线最先射到的点,也就是说,每一条不同斜率的视线,仅且只有一个点
因为这个图是关于 y=x 对称的,所以我们只需要考虑一边
设原点O(0,0)【方便起见】,y=x下半部分可以看到的点有:
(2,1) (3,1) (4,1) (5,1)
(3,2) (4,3) (5,2)
(5,3)
(5,4)
有一个很显然的结论:当gcd(x,y)=1时,就是可以该斜率可以看到的点
因为和他斜率相同的点一定是(kx,ky),换句话说,当x,y互质时,就是满足条件的点
所以,本题转变为了求 2~N 的欧拉函数之和
Attention:
- 在计算时我们排除了三个特殊点,所以 ans=3+2*euler()
- 注意特判 1 !
code
#include<stdio.h> #include<algorithm> using namespace std; const int MX=41000; int n,ans; int phi[MX]; int euler() { for(int i=2;i<=n;++i) phi[i]=i; for(int i=2;i<=n;++i) if(i==phi[i]) { for(int j=i;j<=n;j+=i) { phi[j]=phi[j]/i*(i-1); } } int tot=0; for(int i=2;i<=n;++i) { tot+=phi[i]; } return tot; } int main() { scanf("%d",&n); if(n==1) { printf("0"); return 0; } n--; ans=(3+2*euler()); printf("%d",ans); return 0; }