P2158 [SDOI2008]仪仗队 (欧拉函数)

26 篇文章 2 订阅

题目链接:

https://www.luogu.org/problemnew/show/P2158

题意:

题目描述

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

输入格式:

共一个数N。

输出格式:

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

题解:

首先需要弄明白什么是欧拉函数,推荐一个写的非常好理解的欧拉函数的博客 :https://blog.csdn.net/ltrbless/article/details/87373633

在这里只简要说明什么是欧拉函数,欧拉函数是小于n的正整数(1 <= n )中与n互质的数的数目(特殊的 : φ(1)=1)

这个题目可以简化为从(0, 0) 点在N * N 的矩阵中连射线,y = k * x ,问你有多少种 k 值。k = \frac{y}{x}  ,当(x, y) 互为质数时,就会产生一个k,这是因为:k = \frac{y \times p}{x \times p},p可以消去,所以问题就转化为,在给定的范围内可以找到多少对互质的x,y。

x轴与y轴单独讨论,还有一个点需要注意,就是(1, 1)点,因为都是对称的,但这个(1, 1)点重合了,所以需要减去1.

还有不懂请看代码,有详细的注释。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<sstream>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#define up(i, x, y) for(int i = x; i <= y; i++)
#define down(i, x, y) for(int i = x; i >= y; i--)
#define MAXN ((int)1e5 + 10)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int phi[MAXN];
//基本类似于素数筛,时间复杂度为:nloglogn
int phi[MAXN];
void phi_table(int n)
{
    memset(phi, 0, sizeof(phi));
    phi[1] = 1;
    for(int i = 2; i <= n; i++){
        if(!phi[i]){
            //这里完全相同于素数筛,phi[i]如果为0,那么i是质数
            for(int j = i; j <= n; j += i)
            {
                if(!phi[j]) phi[j] = j; //为了下一行代码,让phi[j]有值
                phi[j] = phi[j] / i * (i - 1);
                // i是j的一个质因子,所以先把这个质因子带入欧拉函数算了,之后再有就再算了
            }
        }
    }
}
int ans;
int main()
{
    int n; scanf("%d", &n);
    if(n == 1){ //当n == 1时特殊情况,因为就他自己,谁也看不到
        puts("0");
        return 0;
    }
    n--; //因为是从 0 - (n - 1) 所以需要减去1,(0,0)点需要特判
    phi_table(n);
    up(i, 1, n) ans += phi[i]; //都加起来
    ans *= 2;  //因为对称
    ans = ans + 2 - 1; //因为需要加上x,y轴上的两个点,再减去重复计算的 (1, 1)这个点.
    cout<<ans<<'\n';
}

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值