Evanyou Blog 彩带

BZOJ2190 [SDOI2008]仪仗队 [欧拉函数]

  题目传送门

仪仗队

Description

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

Input

  共一个数N。

Output

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

Sample Input

  4

Sample Output

  9

HINT

 

【数据规模和约定】   对于 100% 的数据,1 ≤ N ≤ 40000

 


  分析:

  画图分析,因为最左边一竖列,最下面一横行和中间的一条对角线都是只能看到一个点,那么我们可以把图拆成两个同样的三角形来看,发现,在$n>=3$时,每增加一行,增加的点的个数就是$i-1$的欧拉函数。那么直接上欧拉函数即可。

  Code:

  

//It is made by HolseLee on 24th July 2018
//BZOJ2190
#include<bits/stdc++.h>
using namespace std;

const int N=1e5+7;
int n,ans,phi[N],q[5007],top;
bool vis[N];

void ready()
{
    phi[1]=1;int k;
    for(int i=2;i<=n;i++){
        if(!vis[i])phi[q[++top]=i]=i-1;
        for(int j=1;j<=top&&(k=i*q[j])<=n;j++){
            vis[k]=true;
            if(i%q[j]){ 
                phi[k]=phi[i]*(q[j]-1);
            } 
            else {
                phi[k]=phi[i]*q[j];break; 
            } 
        } 
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    if(n<=2){
        if(n==1)cout<<'0'<<"\n";
        else cout<<'3'<<"\n"; 
        return 0;
    }//特判
    ready();
    for(int i=3;i<=n;i++)
        ans+=phi[i-1];
    ans=ans*2+3; //这里要加上最近的三个点
    cout<<ans<<"\n";
    return 0;
} 

 

 

 

posted @ 2018-07-24 16:50  HolseLee  阅读(140)  评论(0编辑  收藏  举报