码迷,mamicode.com
首页 > 其他好文 > 详细

P2158 [SDOI2008]仪仗队

时间:2018-12-15 15:52:48      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:scan   中间   bre   scanf   mat   stream   clu   数学   注意   

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]仪仗队

标签:scan   中间   bre   scanf   mat   stream   clu   数学   注意   

原文地址:https://www.cnblogs.com/gzygzy/p/10123387.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!