1. 程式人生 > >【Luogu-P2158】儀仗隊

【Luogu-P2158】儀仗隊

題目連結

題目描述:

作為體育委員,C君負責這次運動會儀仗隊的訓練。儀仗隊是由學生組成的N * N的方陣,為了保證隊伍在行進中整齊劃一,C君會跟在儀仗隊的左後方,根據其視線所及的學生人數來判斷隊伍是否整齊(如下圖)。
現在,C君希望你告訴他隊伍整齊時能看到的學生人數。
這裡寫圖片描述

解析:

觀察發現,以觀察點的右上為第1行第1列,則能被看到的點(x,y)在第x行第y列,必須滿 **gcd(x,y)==1** 才能被看到,
由圖的對稱性故最後答案應為:
2×(Φ(2)+Φ(3)+....+Φ(N1))+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; }