問題:求 0-n 內素數的個數。
預備知識
什麼是素數:素數(又叫質數),與之相反的是合數。素數的因數只有 1和他本身,例如:7 = 1 * 7。而 6 = 1 * 6 = 2 * 3,因此6不是素數。 規定:0 和 1 既不是 素數 也不是 合數。
判斷素數:如果乙個數 x 是素數,那麼在整數範圍 [2,√x ] 之間,找不到任何能整除x 的整數。為什麼只需要嘗試到 √x ,而不是 n-1 呢?(肯定不是n呀,因為n是他本身,判斷 n 就和判斷 1 一樣,沒有意義的)。
√x 的由來:乙個正數 n ,可以表示成:n = √n * √n 。n 的兩個因數有以下兩種可能:• 兩個因數都為 √n •乙個因數大於 √n,另乙個因數一定小於 √n。如果我們在 2 到 √n 之間找不到乙個因數的話,那麼對應的在 √n 到 n-1 的範圍內 絕對也找不到另外乙個因數。而素數所期待的不正是 2 到 n-1 的範圍內找不到兩個因數,只希望因數為 1 和 n 嗎?
1注意:在第10行中的for迴圈內,使用的是 j * j <= i ,而不是 j <= sqrt(i)。原因:第一:sqrt是用來處理浮點數的,而浮點數的計算速度遠遠慢於integer。第二,函式呼叫也會造成時間的浪費。第三:浮點數的儲存誤差可能引出致命錯誤,如 sqrt(9) 可能等於 2.9999999 ,那麼 int(sqrt(9)) 就等於2 而不是3。篩選法:在一張紙上寫上 1-n 全部整數,然後逐個判斷是否為素數,找出乙個非素數,就把它挖掉,最後剩下的就是素數。public
void countprime_1(int
n) 19}20
}2122/**
23* 此部分內容在接下來將不寫
24*/
25int count = 0;
26//
下標從2開始,是因為 1 不是素數也不是合數,沒有必要判斷
27for (int i = 2; i <= n; i++) 32}
33 }
具體做法如下:
先將 1 挖掉(因為1不是素數)
用 2 去除它後面的各個數,把能被 2 整除的數挖掉,即把 2 的倍數挖掉
用 3 去除它後面各數,把 3 的倍數挖掉
分別用 4、5 等數作為除數去除這些數以後的各數。這個過程一直進行到在除數後面的數已全被挖掉為止
剩下的數就是素數
1對於乙個數p,會依次去除p*p , p*(p+1) , p*(p+2) .... p*(p+k)【p*(p+k)<=n】public
void countprime_2(int
n) 20}21
}22}23 }
前面不是說要去除 p 的所有倍數的嗎?那p*2 ,p*3,p*4 ... p*(p-1)怎麼不去除呢?
他們已經被去除了。因為當前我們要消去 p 的倍數,那麼,之前一定去除了2 3 4 ...p-3 , p-2 ,p-1的這些數 的倍數,舉個例子:之前一定去除了 2*p 3*p 4*p (p-1)*p。所以 , 當想去除p的倍數時,如果我們還是去除 p*2 p*3 p*4 p*(p-1) 那麼豈不是與 我們去除2的倍數時 會去除 2*p 、去除3的倍數時 會去除 3*p、去除4的倍數時 會去除 4*p 重複了 ???
求N!末尾有多少個0
思考 該題實際上是求 2 5 因子對的個數。對於任意乙個階乘,5因子的個數總是小於2因子的個數,僅需考慮n 中5因子的個數 方法 1 將該數用 5 除,得到的商取整數。2 然後再用所得商當被除數除以 5,得到的商取整數。3 持續做到商等於 0 為止。4 過程中的商加總即為階乘的尾數 0 的個數。例 ...
求N 後面有多少個0
從輸入中讀取乙個數n,求出n!中末尾0的個數。輸入有若干行。第一行上有乙個整數m,指明接下來的數字的個數。然後是m行,每一行包含乙個確定的正整數n,1 n 1000000000。對輸入行中的每乙個資料n,輸出一行,其內容是n!中末尾0的個數。33 1001024024 25310 2 5,求出1 n...
2012 09 03 求N 末尾有多少個0
n 末尾有都少個0,首先追本溯源0是怎麼得來的,所有的0都是由質因數2和5相乘得到的。那麼對所有的n 在內的n個數進行質因數分解,只需要計算2和5的個數,取其中較小的乙個,即能得到n 有多少個0。1 要對n個數進行質因數分解,採取最暴力的方式也能解決,當n很大的情況下就不再適用了,那麼有沒有一種方法...