P2158 [SDOI2008]仪仗队
Posted gzygzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2158 [SDOI2008]仪仗队相关的知识,希望对你有一定的参考价值。
P2158 [SDOI2008]仪仗队
数学理性分析一下
把图看成三部分,中间的分割线是一部分,两边各是一部分
前面的人挡住后面的人的条件是,两个人在同一条直线上.
把C君处在的位置看成原点,表述出来就是.
[y=k*x]
因为有(y * a = k * x * a)
所以我们只要求出[gcd(x,y) == 1]的时候的贡献就ok了
那就是[sum_{i=1}^{n-1}phi(i)]
最后把答案*2+1即可.
需要注意的是.
n == 1的时候,答案是0
#include <iostream>
#include <cstdio>
#define rep(i , x, p) for(register int i = x;i <= p;++ i)
#define gc getchar()
#define pc putchar
#define ll long long
const int maxN = 40000 + 7;
int num , prime[maxN], phi[maxN];
bool is_prime[maxN];
ll sum[maxN] , g[maxN];
inline void init() {
int N = 40000;
phi[1] = 1;
rep(i , 2, N) {
if(!is_prime[i]) prime[++ num] = i , phi[i] = i - 1;
for(register int j = 1;j <= num && i * prime[j] <= N;++ j) {
is_prime[i * prime[j]] = true;
if(i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * ( prime[j] - 1 );
}
}
}
int main() {
int n;
init();
ll sum = 0;
scanf("%d",&n);
if(n == 1) return printf("%d",0) , 0;
rep(i , 1, n - 1) sum += phi[i];
printf("%lld",sum * 2 + 1);
return 0;
}
以上是关于P2158 [SDOI2008]仪仗队的主要内容,如果未能解决你的问题,请参考以下文章