【Luogu-P2158】仪仗队

题目链接

题目描述:

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

解析:

观察发现,以观察点的右上为第1行第1列,则能被看到的点(x,y)在第x行第y列,必须满 **gcd(x,y)==1** 才能被看到,
由图的对称性故最后答案应为:

2×(Φ(2)+Φ(3)+....+Φ(N1))+3 2 × ( Φ ( 2 ) + Φ ( 3 ) + . . . . + Φ ( N − 1 ) ) + 3

最后加3是对角线、左、右能看到的人。
/*
  由于(k*x,k*y) 会被 (x,y) 遮挡,于是要求出 gcd(x,y)==1 的个数,即为欧拉函数,但要乘上2,再加上(0,1),(1,0),(1,1)

 */
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<set>
#define rep(a,b,c) for(register int a=b;a<=c;a++)
#define REP(a,b,c,d) for(register int a=b;a<=c;a+=d)
#define Set(a,b) memset(a,b,sizeof(a))
#define frep(a,b,c) for(register int a=b;a>=c;a--)
#define Start(x) for(register int v,i=head[now];i;i=a[i].next)
using namespace std;
const int N=1e7+10;
bool vis[N];
int prime[N];
int phi[N];
int main()
{
    int n;
    scanf("%d",&n);
    vis[1]=1;vis[0]=1;
    register int tot=0;
    phi[1]=1;
    phi[0]=0;
    rep(i,2,n){
        if(!vis[i]) {prime[++tot]=i;phi[i]=i-1;}
        rep(j,1,tot){
            if(1ll*i*prime[j]>n) break;
            vis[i*prime[j]]=1;
            if(i%prime[j]==0) {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            phi[i*prime[j]]=phi[i]*(phi[prime[j]]);
        }
    }
    register int ans=0;
    rep(i,2,n-1){
        ans+=phi[i];
    }
    printf("%d\n",(ans<<1)+3);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值