1. 程式人生 > >2190. [SDOI2008]儀仗隊【歐拉函數】

2190. [SDOI2008]儀仗隊【歐拉函數】

www. 歐拉 一個 運動會 esc pre 訓練 現在 int

Description

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

Input

  共一個數N。

Output

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

Sample Input

  4

Sample Output

  9

HINT

【數據規模和約定】   對於 100% 的數據,1 ≤ N ≤ 40000

首先設左下角坐標為(0,0)

那麽很容易發現:
一個人如果是不可視的,那麽他的坐標(x,y)一定含有公約數k
使得一個人(x/k,y/k)可以擋住他。
那麽只要一個人的橫縱坐標互質,就是可以被看見的
那麽問題就轉化成了對於每個1~n中的數,有多少個1~n的數與其互質
然後我們又可以發現答案關於(0,0)->(n,n)軸對稱
所以我們只算一半即可。
然後就可以把問題轉化為求和歐拉函數的φ(1)~φ(n)了
註意n=1的時候特判一下

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 int ans,n,phi[40005
]; 5 6 void Euler() 7 { 8 phi[1]=1; 9 for (int i=2;i<=40000;++i) 10 if (!phi[i]) 11 for (int j=i;j<=40000;j+=i) 12 { 13 if (!phi[j]) phi[j]=j; 14 phi[j]=phi[j]/i*(i-1); 15 } 16 } 17 18 int main() 19
{ 20 scanf("%d",&n); 21 Euler(); 22 for (int i=1;i<n;++i) 23 ans+=phi[i]; 24 printf("%d",ans*2+(n!=1)); 25 }

2190. [SDOI2008]儀仗隊【歐拉函數】