首页 > 代码库 > [SDOI 2008]仪仗队

[SDOI 2008]仪仗队

Description

作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。现在,C君希望你告诉他队伍整齐时能看到的学生人数。

技术分享

Input

共一个数N

Output

共一个数,即C君应看到的学生人数。

Sample Input

4

Sample Output

9

HINT

【数据规模和约定】

对于 100% 的数据,1 ≤ N ≤ 40000

题解

如图建系:技术分享

注意到“某人被挡住”即某人的坐标可以约分。

我们先不考虑坐标轴上的点。

那么先算$1~n-1$这个范围内所有满足题意的点,先考虑$y<x$

$$\sum_{x=1}^{N-1}\sum_{y=1}^{x-1}[gcd(x,y)=1]$$
转化为

$$\sum_{x=1}^{N-1}φ(x)$$

做完之后我们将算出来的$ans×2$得到$y>x$的情况。

由于没考虑坐标轴上的点,我们再将$ans+2$,

由于没考虑$φ(1)=1$,我们再将$ans+1$。

 

 1 #include<map>
 2 #include<set>
 3 #include<ctime>
 4 #include<cmath>
 5 #include<queue>
 6 #include<stack>
 7 #include<cstdio>
 8 #include<string>
 9 #include<vector>
10 #include<cstdlib>
11 #include<cstring>
12 #include<iostream>
13 #include<algorithm>
14 #define LL long long
15 #define RE register
16 #define IL inline
17 using namespace std;
18 const int N=40000;
19 
20 int n;
21 
22 bool isprime[N+5];
23 int prime[N+5],top;
24 int phi[N+5];
25 IL void Pre();
26 
27 int main()
28 {
29     scanf("%d",&n);
30     Pre();
31     LL ans=0;
32     for (RE int i=1;i<n;i++)
33         ans+=phi[i];
34     printf("%lld\n",ans*2+3); 
35     return 0;
36 }
37 
38 IL void Pre()
39 {
40     for (RE int i=2;i<=n;i++)
41     {
42         if (!isprime[i]) phi[i]=i-1,prime[++top]=i;
43         for (RE int j=1;j<=top&&i*prime[j]<=n;j++)
44         {
45             isprime[i*prime[j]]=1;
46             if (!(i%prime[j])) {phi[i*prime[j]]=phi[i]*prime[j];break;}
47             else phi[i*prime[j]]=phi[i]*phi[prime[j]];
48         }
49     }
50 }

 

[SDOI 2008]仪仗队