ACM中素數(prime)操作入門解析

2021-07-05 05:41:35 字數 2953 閱讀 7718

acmacm中對素數的操作是極為頻繁,對素數的操作並不難,但對於初學者的還是有一定的挑戰,我們來對其進行分析對素數的判斷在新手中最常見的一種辦法,就是暴力求解,

bool isprime=false;

for(int i=2;i*i<=n;++i)

if(n%i==0)

這是一種非常常見的新生級演算法,他在素數判斷上的位置等價於氣泡排序選擇排序在排序中的地位,而在排序上我們最終選擇了堆排序,快排,分治等一系列nlogn

級別的演算法,那麼在素數判斷上我們該如何抉擇? 

那就是 篩選法,首先,我們先來確定一件眾所周知的事情,任何數,當然0

不算,而且還要是整數範圍內的數,只要符合這以上幾點,那麼他就可以拆分為由幾個相同或不相同的素數所乘,比如

5=1*5

,12=2*2*3

,負數的話在加個

-1,每個非

0非1整數的絕對值都對應著乙個質數序列,一一對應也就是滿射,這說明了什麼?判斷乙個數是不是質數你並不需要從2

到sqrt(n)花費

sqrt(n)

的時間來計算,如果你明確了從1到

n之間的所有質數,那麼用質數誒個除就好了。

你問我如果n

就是質數怎麼辦?是不是要把1到

n之間的質數序列都遍歷一邊?當然不,只要遍歷到某個質數

>sqrt(n)

就好了,為什麼?都遍歷到某個數

a>sqrt(n)

了,說明這個數

n對應的質數序列裡最小的質數,也就是他的最小質因數大於

sqrt(n)

,這明顯不合理,

100可能有大於

10的最小質因數嗎?不可能,因為如果有的話,設這個最小質因數為

i依據之前每個正整數對應乙個質數序列的定理,

100=i*

(某個質數序列)因為

i為最小質因數,所以「某個質因數序列」必然

>=i 

這就導致了等號左右不相等。

所以,乙個比較好的素數判定演算法是這樣的。

int prime[numofprime];//乙個現成的質數序列

bool isprime=false;

for(int i=0;in) break;

if(n%prime[i]==0)

}

接下來,就談到了利用篩選法對prime

的初始化操作,不過其實相等簡單,依舊是利用

最初的每個數與質數序列一一對應的定理,不過我們還要加乙個相等顯而易見到無腦的結論,那就是那些質數序列裡的數一定比他們相乘所得的數小,這意味著什麼呢?著意味著每乙個合數包含的質數序列中的數都是在之前出現過的。

所以,**如下

#include #include #include int primer[100001];//我們初始化了從1到200000之間的所有質數在primer中,當然,質數數量肯定不滿200000個,而且質數除了2都是奇數,所以這裡其實只要10000即可

bool vis[100001];//vis記載了我們對質數的判斷,vis的大小決定了我們質數判定的範圍,這裡判定範圍為1-200000,vis使用了10001大小的理由同上

int numofprimers;//記錄了prime的數量

bool isprimer(unsigned int i)//質數的判斷

return true;

}int main()

//printf("%d", numofprimers);

int t; unsigned int n;

scanf("%d", &t);

while (t--)

return 0;

}

以上就是篩選法得到質數從而簡化質數判定的方法,每乙個vis[i]都代表乙個奇數,vis[0]代表3,vis[1]代表5,當我們的i=0時,vis[0]的值為false 

說明3沒有被訪問,3是質數,然後我們向後遍歷,將因數中含有3的奇數訪問一遍,在i=1之前,vis[3]代表的9,vis[6]代表的15都被加上了true,

代表不是質數,所以,當vis[i]==false時,就代表他是個質數,因為他無法被之前比他小的所有質數所除,他的質因數就為他本身,當然了,覺得這行**

有點難受的同學不要著急,這是被acm界的前輩優化過的**,有非常好的效率,雖然看起來有那麼一點點複雜,所以平常情況下我們可以犧牲一點效率

使用一下簡易版本

#include #include using namespace std;

int primer[100001];

bool vis[200001];

int numofprime = 0;

void initprimer()

}int main()

是不是美觀多了呢,平常就這樣寫寫也沒有多少關係,不過有一點很重要,大家注意到了primer與vis裡的資料裡吧,100001與200001,建議不要 

使用數字,使用巨集或者const int常量比較好,這是一種很符合規範的程式設計習慣

使用篩選法得到一定範圍內的質數資料然後去判斷素數是非常高效的,但是但是,依然有缺點,因為他的資料是非常依靠vis這個陣列的

而陣列的大小是有上限的0x7fffffffffff,也就是int的最大值,這意味著什麼呢?這意味著在我們一般人電腦上,直接使用這個方法去判定從

1到某個longlong級別的資料之間的質數是有點困難的,對此,我們可能就需要借助我們最初的方法,遍歷,雖然低效但是可靠,當超出了

我們能夠判定的範圍時,就需要結合使用這個遍歷方法來繼續判斷

python 入門 查詢指定列表中的素數

python簡單方法找出指定列表中的素數 定義乙個函式,傳入乙個數,判斷該數字是否為素數 defget prime num 如果這個數字num能在小於它的數字裡面找到乙個數能和它整除,則不是素數 for i in range 2 num if num i 0 return false 如果不是素數,...

在MVC中Dashboard基礎入門操作

devexpress中的dashboard這個圖形外掛程式真的很好用,只需要在設計器繫結資料就行了,完全不用寫後台 我也是剛學這個外掛程式,可能還有一些我沒有了解的知識點,忘各位大佬不吝賜教.我寫這篇博文也是為了給想我一樣剛研究這個外掛程式的博友們一些我的總結,給各位節省一些時間,哈哈.1.當我們建...

Matlab入門(二) 程式設計中的基本操作

1 輸入數字語法 x input prompt 示例 prompt what is the original value?x input prompt y x 10顯示 what is the original value?3 x 3 y 302 輸入文字語法 str input prompt,s ...