SDOI 2008 仪仗队

你说的曾经没有我的故事 提交于 2019-12-02 03:06:57

洛谷 P2158 [SDOI2008]仪仗队

洛谷传送门

题目描述

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

现在,C君希望你告诉他队伍整齐时能看到的学生人数。

输入格式

共一个数N

输出格式

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

输入输出样例

输入 #1复制

输出 #1复制

说明/提示

【数据规模和约定】

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

题解:

一道欧拉函数的经典题。原题是POJ 3090 Visible Lattice Points

来看图说话:

观察这个图,我们首先发现,这个东西是关于直线\(y=x\)对称的。接下来我们观察遮挡,根据几何学中的相似知识(三角形相似),我们发现,如果有两个点的横纵坐标构成的两个三角形相似的话,那么那个较大的三角形(那个点)就会被挡住。

什么意思呢?我们发现,一个点可见的条件为:当且仅当\((x,y)\in N,x\not=y\)并且\(gcd(x,y)=1\),即横纵坐标互质。

因为这个图像的大小已知,并且这个图像是关于\(y=x\)对称的,那么我们只需要考虑半边的图像有多少点,给它乘二加三(因为有\((1,0),(1,1),(0,1)\))即可。

不需要双层循环进行枚举,只需要用一层循环枚举\(y\),因为是关于\(y=x\)对称的,所以\(x\in [1,y)\),那么,符合条件的\(x\)的数量就是\(y\)的欧拉函数\(\Phi (y)\)

所以,答案为:
\[ \sum_{i=2}^{n-1}\Phi(i)\times 2+3 \]

为什么是到\(n-1\)而不是到\(n\)呢?因为原点的坐标是\((0,0)\),而这个点不能被统计到答案中去(自己不能孤芳自赏),是从0计数的。

然后就简单了,一遍线筛筛选出欧拉函数数组,直接统计答案即可,复杂度是\(O(n)\)的。

关于欧拉函数的知识点,如有不太清楚的,敬请移步到本蒟蒻的这篇博客:

浅谈欧拉函数

代码:

#include<cstdio> using namespace std; const int maxn=40010; int phi[maxn],v[maxn],prime[maxn]; int n,cnt,ans; void euler(int n) {     cnt=0;     for(int i=2;i<=n;i++)     {         if(!v[i])             prime[++cnt]=i,phi[i]=i-1;         for(int j=1;j<=n && i*prime[j]<=n;j++)         {             v[i*prime[j]]=1;             if(i%prime[j]==0)             {                 phi[i*prime[j]]=phi[i]*prime[j];                 break;             }             else                 phi[i*prime[j]]=phi[i]*phi[prime[j]];         }     } } int main() {     scanf("%d",&n);     if(n==1)     {         printf("0");         return 0;     }     euler(n);     for(int i=2;i<n;i++)         ans+=phi[i];     printf("%d",ans*2+3);     return 0; }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!