[SDOI2008]儀仗隊(歐拉篩裸題)
阿新 • • 發佈:2018-06-09
ret 其他人 輸入輸出格式 不同 tex 多次 是否 highlight urn
題目描述
作為體育委員,C君負責這次運動會儀仗隊的訓練。儀仗隊是由學生組成的N * N的方陣,為了保證隊伍在行進中整齊劃一,C君會跟在儀仗隊的左後方,根據其視線所及的學生人數來判斷隊伍是否整齊(如右圖)。 現在,C君希望你告訴他隊伍整齊時能看到的學生人數。
輸入輸出格式
輸入格式:
共一個數N
輸出格式:
共一個數,即C君應看到的學生人數。
思路:
典型的歐拉篩
為了幫助萌新,我先從歐拉函數開講
什麽是歐拉函數?
定義:與一個數的約數有且只有1的數(互質)的個數(比如說2有1一個,6有1,5兩個)
性質:積性函數(Phi(i)等於他的所有質因數的phi值的乘積)
為什麽能這麽做呢?
其實這道題求的是有多少種不同的斜率
為什麽呢?
看圖:
很顯然,一個斜率上只能看到一個人,該斜率其他人都會被堵得死死的。。。
那麽,每一個獨立的斜率又如何表示呢?
我們用數對(x,y)表示斜率
我們知道,如果x,y不互質,那麽他們可以同時除以他們的最大公約數(設為k),則該斜率可表示為(x/k,y/k)
很顯然會有重復
所以為了避免重復,我們所求的是互質點對的個數
互質點對很顯然就是歐拉函數
這裏我用的是(nlogn)的算法——埃氏篩
從2開始,一個數i如果因數標記為1,則他是素數,他的歐拉函數值為i-1,同時,利用它來更新所有它的倍數的因數標記,如果因數標記大於1,則其不是素數,根據積性函數的性質,Phi[i]=其各因數的乘積,當其含有多次方因子時(比如8=2^3),那麽Phi[i]的值為phi[2]*2*2;
不說了,代碼:
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; long long ll; long long e[40010]; long long n,ans; int main() { ans=2; cin>>n; if(n==1) { cout<<0; return 0; } for(int i=1;i<=n;++i) { e[i]=i; } for(int i=2;i<=n;++i) { if(e[i]==i) { for(int j=i;j<=n;j+=i) { e[j]=e[j]/i*(i-1); } } } n--; for(int i=2;i<=n;++i) { ans+=e[i]*2; } cout<<ans+1; }
[SDOI2008]儀仗隊(歐拉篩裸題)