BZOJ2190 [SDOI2008] 仪仗队

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2190

Description

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

 

Output

共一个数N。

Output

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

Orz出题人,能把数论题变成这样子真不容易

LSJ教主的题解:

假设C君为(0, 0), 则右上方为(n - 1, n - 1).

一个点(x, y) 能被看到的前提是gcd(x, y) = 1, 所以 answer = ∑ phi(i) * 2 + 2 - 1 = ∑phi(i) * 2 + 1 ( 1 <= i < n ). +2是因为(1, 0), (0, 1) 两个点, -1是因为(1, 1)重复计算了

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #define rep(i,l,r) for(int i=l; i<=r; i++)
 6 #define clr(x,y) memset(x,y,sizeof(x))
 7 using namespace std;
 8 const int maxn = 40010;
 9 int n,cnt=0,pri[maxn],phi[maxn];
10 bool flag[maxn];
11 void get_euler(){
12     clr(flag,0); phi[1] = 1;
13     rep(i,2,n){
14         if (!flag[i]) pri[++cnt] = i, phi[i] = i - 1;
15         for(int j = 1; j <= cnt && i*pri[j] <= n; j++){
16             flag[i*pri[j]] = 1;
17             if (i % pri[j]) phi[i*pri[j]] = phi[i] * (pri[j] - 1);
18             else{
19                 phi[i*pri[j]] = phi[i] * pri[j];
20                 break;
21             }
22         }
23     }
24 }
25 int main(){
26     scanf("%d",&n);
27     get_euler();
28     int ans = 0;
29     rep(i,1,n-1) ans += phi[i] << 1;
30     printf("%d
",ans+1);
31     return 0;
32 }
View Code
原文地址:https://www.cnblogs.com/jimzeng/p/bzoj2190.html