第一次寫部落格。
今天學了兩個很簡單的定理,老是忘記細看,今天可算看了下。
其中乙個是
素數打表的優化
首先先理解了簡單的埃篩法;
埃篩法就是把表中全部數為素數的倍數乙個個篩除,最後只有素數留在表中。
#include#includeusing namespace std;
#define maxn 100000
int check[maxn]=;
int prime[maxn]=;
int main()
} for(int i=0;i時間複雜度為o(n loglog n);
接下來是更為優化的尤拉線性篩法(時間複雜度為o(n))
/*求小於等於n的素數的個數*/
#include#includeusing namespace std;
int main()
{ int n, cnt = 0;
int prime[100001];//存素數
bool vis[100001];//保證不做素數的倍數
scanf("%d", &n);
memset(vis, false, sizeof(vis));//初始化
memset(prime, 0, sizeof(prime));
for(int i = 2; i <= n; i++)
{if(!vis[i])//不是目前找到的素數的倍數
prime[cnt++] = i;//找到素數~
for(int j = 0; jif(i % prime[j] == 0) break;←_←這一步比較難理解
解釋:首先,任何合數都能表示成多個素數的積。所以,
任何的合數肯定有乙個最小質因子。我們通過這個最小質因子就可以判斷什麼時候不用繼續篩下去了。
當i是prime[j]的整數倍時(i % prime[j] == 0),i*prime[j+1]肯定被篩過,跳出迴圈。
因為i可以看做prime[j]*某個數x, i*prime[j+1]就可以看做 prime[j]*x*prime[j+1] 。而 prime[j] 必定小於 prime[j+1],
所以 i*prime[j+1] 這個合數已經被x*prime[j](prime[j]是這個合數的最小質因子)篩掉,就不用再做了
也就是:
i=prime[j]*x;
合數=i*prime[j+1]=i*prime[j]*x; //prime[j]是合數的最小質因子!
同時我們可以發現在滿足程式裡的兩個條件的時候,prime[j]必定是prime[j]*i的最小質因子。這個性質在某些題裡可以用到。
/*參考了
ACM 素數線性篩法(素數打表)
題目 include include int prime 700000 bool check 10000000 int num 1 int judge int y int j 0 while p j 1 j j i 0 while i j i j return1 int main int j 1 f...
美素數 素數打表
description 小明對數的研究比較熱愛,一談到數,腦子裡就湧現出好多數的問題,今天,小明想考考你對素數的認識。問題是這樣的 乙個十進位制數,如果是素數,而且它的各位數字和也是素數,則稱之為 美素數 如29,本身是素數,而且2 9 11也是素數,所以它是美素數。給定乙個區間,你能計算出這個區間...
高效素數打表
大家所知的素數打表時間複雜度幾乎都是n2。就是這種 void init prime j 0 for i 2 i 1000002 i if prime i prime j i 在網上搜到了另一種方法,效率提高了不少。巧妙之處還在研究中,等理解差不多就仔細分析一下。下面是 大家可以發表一下自己的看法,交...