【Luogu-P2158】儀仗隊
阿新 • • 發佈:2019-02-12
題目描述:
作為體育委員,C君負責這次運動會儀仗隊的訓練。儀仗隊是由學生組成的N * N的方陣,為了保證隊伍在行進中整齊劃一,C君會跟在儀仗隊的左後方,根據其視線所及的學生人數來判斷隊伍是否整齊(如下圖)。
現在,C君希望你告訴他隊伍整齊時能看到的學生人數。
解析:
觀察發現,以觀察點的右上為第1行第1列,則能被看到的點(x,y)在第x行第y列,必須滿 **gcd(x,y)==1** 才能被看到,
由圖的對稱性故最後答案應為:
最後加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;
}