[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君应看到的学生人数。
输入输出样例
说明
【数据规模和约定】
对于 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]仪仗队的主要内容,如果未能解决你的问题,请参考以下文章