題目
首先我們先把題目分析一下。
emmmm,這應該是乙個找規律,應該可以打表,然後我們再分析一下,發現如果這個點可以被看到,那它的橫座標和縱座標應該互質,而互質的條件就是它的橫座標和縱座標的最大公約數為一,那這題的意思就變成了,在乙個n * n的方格內尋找所有點的橫座標和縱座標互質的點的個數。
但是這樣複雜度肯定是過不去的。打表時間花費也是很多的,所以我們需要找到加快速度的方法,就是用尤拉函式來加快速度,所以我們就要實現大的優化,我們先明確尤拉函式是個什麼東西.
\(φ(x)\)表示在\(1\)到\(x - 1\)中所有與x互質的數的個數。這個函式一般就叫做尤拉函式。這個函式還具有一些性質.
如果\(x\)是質數,那\(φ(x)=x-1\)。(質數的性質就是這樣)
若\(m\)與\(n\)互質,那\(φ(n * m)= φ(n)* φ(m)\).(可以根據乘法原理推出)
當\(x\)是質數時,那\(φ (x^k)=(x-1)×x^\)
所以我們可以通過觀察和推算發現,如果想求出結果,那就是對於圖的每個橫座標,都記錄他的尤拉函式的值,然後加起來就是最終結果。然後把結果乘2,因為縱座標也需要進行一波這樣的操作。最後再加上一(因為2,2這個點也算)
那到底應該怎麼篩使得尤拉函式能夠很快的算出來呢。
這裡我們就要引進兩個演算法——線性篩和尤拉篩。
線性篩是指以線性的時間篩素數,尤拉篩是以線性的時間求出尤拉函式。
而且他們之間有著異曲同工之妙。
**:
#include #include #include #define maxn 100010
int prime[maxn];//表示第幾個質數。
bool vis[maxn] = ;//判斷是否為質數,如果是則為0
int tot;
int main()
}}
我們分析上面的**,唯一可能難理解的地方就是\(break\)的那個判斷了。這也是尤拉篩的精髓所在,如果已經超出了範圍需要退出,這個自不必多說,但是,如果\(i\%prime[j]==0\)時,為啥就要退出呢
原理:首先我們需要明白一些性質:
我們篩素數時應該從小到大篩,方便後面優化時間,所以源**迴圈中\(i\)是從小到大篩的。
當\(i\%prime[j]==0\)時,則\(i\)為\(prime[j]\)的倍數,設\(i\)為\(prime[j]*k\),如果繼續向下篩的話,下乙個要篩的數是\(i*prime[j+1]=prime[j]*k*prime[j+1]\);此時要篩的數即\(i*prime[j+1]\)就已經被\(prime[j]\)篩去了,而根據性質1,\(prime[j]\)要比\(i\)小(因為\(i\)是\(prime[tot]\))。
因此時間複雜度是線性的。
尤拉篩其實跟線性篩差不了多少。
首先我們應該熟記尤拉函式的性質。並且這種篩法還可以進行線性求積性函式。
原理我們看線性篩的第二個性質,尤拉函式是不是也滿足,因此防止多餘的運算
memset(isprime, 1, sizeof(isprime));
isprime[1] = false;
for (int i = 2; i <= listsize; i++)
for (int j = 1; j <= primesize && i * prime[j] <= listsize; j++)
phi[i * prime[j]] = phi[i] * (prime[j] - 1)//即phi[j];因為他們互質,所以可用性質1,2
}}
洛谷P2158 儀仗隊
作為體育委員,c君負責這次運動會儀仗隊的訓練。儀仗隊是由學生組成的n n的方陣,為了保證隊伍在行進中整齊劃一,c君會跟在儀仗隊的左後方,根據其視線所及的學生人數來判斷隊伍是否整齊 如下圖 現在,c君希望你告訴他隊伍整齊時能看到的學生人數。輸入格式 共乙個數n 輸出格式 共乙個數,即c君應看到的學生人...
洛谷P2158儀仗隊(數學,觀察找規律,尤拉函式)
讀完題被嚇到了,這是什麼東西。總之,需要觀察 找規律啊!觀察可以發現,從第三行開始,第i行中當前直角三角形範圍內能觀察到的點數等於 i 1 的尤拉函式值 1 include 2 include 3 include 4 include 5 include 6 using namespace std 7...
線性篩(尤拉篩)
昨天的考試跪的一塌糊塗 第一題水過,第二題帶wa的樸素,最後題忘了特判左端點全跪,分數比起預計得分整整打了個對折啊!步入正題 線性篩 尤拉篩 一般的篩法 ppt裡叫埃拉託斯特尼篩法,名字異常高貴 的效率是o nlglgn 其實很接近o n 啊!對於一些例如n 10000000的殘暴資料會跪,於是,線...