[SDOI2008]仪仗队

Posted aptx--4869

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SDOI2008]仪仗队相关的知识,希望对你有一定的参考价值。

昨天18 今天初赛(⊙o⊙)
我决定好好整理记录做过的题目了
虽然并没有多大关系,总觉得这可以算是一个节点,可以是一个稍作转变的契机

于是...针对上次模拟赛T1那么简单的规律都没找到这一点,今天做了些数论(尤其是找规律)的题目

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

题目描述

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

输入输出格式

输入格式:

共一个数N

输出格式:

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

输入输出样例

输入样例#1:
4
输出样例#1:
9

说明

【数据规模和约定】

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

 

首先想到的打表找规律 O(n^2)
从(0,0)点斜向右上做射线,如果有两个点斜率相同,那肯定只能看到最近的一位
=> 如果存在两个点(x1,y1)和(x2,y2)使x1/y1=x2/y2 (x1<x2,y1<y2)那(x2,y2)肯定是会被挡住的,又因为点的坐标都是整数,那x2、y2就是x1、y1的整数倍
=> 不被挡住的点一定是约分约到最简的,即(x,y)点的x和y最大公约数是1
=> gcd

/*36*/
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n;
int ans;
inline int findgcd(int a,int b){
    return !b?a:findgcd(b,a%b);
}
int main(){
    scanf("%d",&n);
    if(n==1){
        printf("0
");
        return 0;
    }
    for(int i=2;i<n;i++){
        for(int j=1;j<i;j++){//j<i
            int gcd=findgcd(i,j);
            if(gcd>1)continue;
            ans++;
        }
    }
    ans=(ans<<1)+3;
    printf("%d",ans);
    return 0;
}

然后,然后就TLE了呀

然后套个while(n<=100)疯狂找规律...

But in vain.

等等
莫不是忘了什么
“x和y最大公约数是1”
“让x、y互质”
“求在n范围内有多少对x,y互质”
欧拉函数诶

#include<iostream>
#include<cstring>
#include<cstdio>
#define N 400005
using namespace std;
int n,ans;
int a[N];
int main(){
    scanf("%d",&n);
    if(n==1){
        printf("0
");
        return 0;
    }
    for(int i=1;i<=n;i++)a[i]=i;
    for(int i=2;i<=n;i++){
        if(a[i]==i){
            for(int j=i;j<=n;j+=i){
                a[j]=a[j]/i*(i-1);
            }
        }
    }
    for(int i=2;i<n;i++) ans+=a[i];
    ans=(ans<<1)+3;
    printf("%d",ans);
    return 0;
}

欧拉函数

 














以上是关于[SDOI2008]仪仗队的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2190: [SDOI2008]仪仗队.

bzoj2190 [SDOI2008]仪仗队

bzoj 2190: [SDOI2008]仪仗队

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

BZOJ-2190: [SDOI2008]仪仗队 (欧拉函数)

bzoj 2190 [SDOI2008]仪仗队