素数筛模板
前言
在判定素數的問題中,隨著不斷學習,里面的拓展性也在不斷地增加。
問題:
判定一個數是否為素數:
想都不想的方法:
static boolean isprime(int value){for(int i=2;i<value;i++){if(value%i==0){return false;}}return true; }暴力從開始判斷的方法。復雜度O(n)。當數據大于1e7左右基本就爆了。更別說多組輸入了
稍微思考數據組成
對于一個數n如果不是素數,一定有a*b=n(a<b);a<根號n,b>根號n,所以只要出現一定是成雙成對。所以你只要找到1個就能說明這個數不是素數。所以從開始遍歷到a是最省時的方法。因為a是log級。算法復雜度為O(logn)所以代碼為:
static boolean isprime(int value) {for(int i=2;i*i<value+1;i++){if(value%i==0){return false;}}return true; }這種情況能夠基本單輸入的素數問題。但是遇到多個輸入肯定也會GG的。
埃拉托斯特尼(Eratosthenes)篩法
問題:多個輸入,問關于素數相關的問題。
如果用上述方法肯定爆。多組輸入的最好解決辦法是打表。至于打表,如果上述的打表nlogn打表的話會TLE,所以就要換一種思考方式。
埃氏篩的核心思想就是將素數的倍數確定為合數。對于一個從2開始連續數據,我們假設其中每一個都是素數。如果一個數為素數,那么這個數的倍數一定也是素數。所以算法大致流程:
2: [i=(2+2)—>(+2)數組尾],4,6,8,10 * * 不是素數
3: [i=(3+3)—>(+3)數組尾],6,9,12 * * 不是素數
4: [i=4]不是素數,跳過
5: . . . . . . . . . . . .
這個到除了前面幾次的計算量多一點,到后面隨著數據增大對整個復雜度相加是比較小的,算法復雜度為O(nloglogn);別小瞧多的這個logn,數據量大一個log可能少不少個0,那時間也是十倍百倍甚至更多的差距。
具體代碼為
歐拉篩——線性篩
對于上述的埃氏篩,雖然能解決大部分的問題。但是不難發現里面還是有挺多不夠精簡的地方,比如有的地方會重復訪問。而歐拉篩在埃氏篩的基礎上進行優化,達到O(n)的復雜度。
static boolean isprime[]; static int prime[]; static void getprimeoula()// 歐拉篩{prime = new int[100001];// 記錄第幾個primeint index = 0;isprime = new boolean[1000001];for (int i = 2; i < 1000001; i++) {if (!isprime[i]) {prime[index++] = i;}for (int j = 0; j < index && i * prime[j] <= 100000; j++){isprime[i * prime[j]] = true;// if (i % prime[j] == 0)break;}}}- 如果對后端、爬蟲、數據結構算法等感性趣歡迎關注我的個人公眾號交流:bigsai
總結
- 上一篇: 全排列两种实现方式(java)—poj2
- 下一篇: 唯一分解定理(算术基本定理)详解——hd