1. 程式人生 > >P2158 [SDOI2008]儀仗隊

P2158 [SDOI2008]儀仗隊

sin 是否 數據 數據規模 9.png radi n) ring 成了

題目描述

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

輸入輸出格式

輸入格式:

共一個數N

輸出格式:

共一個數,即C君應看到的學生人數。

輸入輸出樣例

輸入樣例#1: 復制
4
輸出樣例#1: 復制
9

說明

【數據規模和約定】

對於 100% 的數據,1 ≤ N ≤ 40000

//Pro:P2158 [SDOI2008]儀仗隊

//把圖上的(1,1)看作是(0,0)
//因為正方形關於對角線對稱
//所以我們只考慮對角線一側的三角形 //可以發現,在一條直線上的點會被這條直線上第一個點遮擋 //所以如果被遮擋的話,那麽他們所在直線的斜率相等 //設有一條直線上的一個點是(x,y) //那麽這條直線的斜率k=y/x //然後我們就可以知道這條線上的第一個點(x0,y0) //且gcd(x0,y0)=1,(x0*t,y0*t)都會被(x0,y0)遮擋 //所以問題就變成了求 sigma(i=2->n-1) // (j=1->i) // gcd(i,j)=1 //也就是求sigma(i=2->n-1) phi(i)
//當然最後還要再*2+3 //因為我們算的是三角,而且沒有算(0,1),(0,1),(1,1) #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=5e4+5; bool flag[N]; int prime[N],cnt; int phi[N]; void init(int n) { int d; flag[1]=1,phi[1]=1; for(int i=2;i<n;++i) {
if(!flag[i]) prime[++cnt]=i,phi[i]=i-1; for(int j=1;j<=cnt&&(d=i*prime[j])<n;++j) { flag[d]=1; if(i%prime[j]) phi[d]=phi[i]*(prime[j]-1); else phi[d]=phi[i]*prime[j]; } } } int n,ans; int main() { scanf("%d",&n); if(n==1) { puts("0"); return 0; } init(n); for(int i=2;i<n;++i) ans+=phi[i]; printf("%d",ans*2+3); return 0; }

P2158 [SDOI2008]儀仗隊