關於質數的一些演算法

2021-09-01 11:22:28 字數 1618 閱讀 8275

首先是基礎中的基礎,怎麼判斷乙個數是不是質數,直接試除就行了,只需要嘗試到sqrt(n),因此時間複雜度o(n^1/2)

public static boolean isprime(long number)
其次是篩法,也就是從乙個範圍內篩選出質數,最直接的辦法是乙個個判斷,這顯然很複雜,因此有了篩法的概念

埃拉託斯特尼篩法,是一種由希臘數學家埃拉託斯特尼所提出的一種簡單檢定素數的演算法。要得到自然數n以內的全部素數,必須把不大於根號n的所有素數的倍數剔除,剩下的就是素數。

這個演算法也很基礎,直接上**

public static listprimenumbers_sieve2(final int start, final int end)

if (cursor>=start) primenumbers.add(cursor);

}for (; cursor<=end ;cursor++)

}return primenumbers;

}

這裡說一下的他的時間複雜度,這裡用到了素數分布的中心定理

素數定理可以給出第n個素數p(n)的漸近估計:

它也給出從整數中抽到素數的概率。從不大於n的自然數隨機選乙個,它是素數的概率大約是1/ln n。

這個演算法對每乙個素數 p, 要進行 n/p 次運算,全部加起來,就是 n * (從 1 到根號 n 之間的 1/p 之和) 

不大於n的質數的倒數和近似於lnln n,這個結論相對常見: 這裡有分析

補充一下關於調和級數的知識

人們已經研究調和數列已經幾百年了.但是迄今為止沒有能得到它的求和公式只是得到它的近似公式(當n很大時):

(於是我們得出 (從 1 到 n 之間的 1/p 之和) 約等於 ln (調和級數), 後者約等於 ln n, 所以前者就是 lnln n.於是時間複雜度即為o(n*loglogn)

上面的篩法,有一些合數被篩選到多次,如6 被2篩一次 被3 也篩一次,尤拉篩的核心思想就是,所有的合數只被他較小的因數篩掉,

**如下

public static listprimenumbers_sieve3(final int start, final int end)

for (int j =0 ; j < count && i * primenumbers[j] <= end; j++ )

}return returnprime;

}

關鍵在於 if (i % primenumbers[j] == 0) break; 這一行,就是說如果被當前篩選的數,如果是某個已篩選數的整數倍,就不用再篩選了(因為肯定都由前面那個較小的因數都篩選過了)

由於每乙個數都只篩選一次,因此時間複雜度是o(n),因此也叫線性篩

因式分解就是用乙個個的質數去試除,因此他首先需要判斷n以內質數的過程

public static listprimefactors2 (int number)

if (number == 1) break;}}

return list;

}

這裡n的取值對時間影響很大,在已有質數列表的情況下,最壞的情況它是o(n)的

當然也有更好的辦法,可以參考這裡

關於演算法的一些資料

1.clrs 演算法導論 演算法百科全書,只做了前面十幾章的習題,便感覺受益無窮。2.algorithms 演算法概論 短小精悍,別據一格,準經典之作。乙個壞訊息 同演算法導論,該書沒有習題答案。好訊息 習題很經典,難度也適中,只需花點點時間自己也都能做出來。不好也不壞的訊息 我正在寫習題的答案,已...

關於陣列的一些演算法

去除陣列裡,重複的元素 方案1,用陣列本身的特性,去重 datetime dt datetime.now string s new string q s.distinct toarray 方案2,相鄰的進行比較,如果不等,則加入list string stringarray s listlistst...

關於A 演算法的一些研究

公式 f g h 代價計算,尋路代價最小的就是我們要找的 g 表示從起點 a 移動到網格上指定方格的移動耗費 可沿斜方向移動 h 表示從指定的方格移動到終點 b 的預計耗費 h 有很多計算方法,這裡我們設定只可以上下左右移動 下面拿個例子說明一下 原文參考 假如從a尋路到b 尋路步驟 1.從起點a開...