SDOI 2008 仪仗队

洛谷 P2158 [SDOI2008]仪仗队

洛谷传送门

题目描述

作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。 img 现在,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;
}
posted @ 2019-10-23 18:25  Seaway-Fu  阅读(186)  评论(0编辑  收藏  举报