求一千萬以內的素數的個數
阿新 • • 發佈:2019-02-03
問題描述:輸入n,輸出小於n的素數的個數,當n等於0時退出程式
輸入:整數n(n<10 000 000)
輸出:小於n的素數的個數,當n等於0時退出程式
首先我們知道,偶數一定不是素數(2除外)
所以我們可以這麼解決這道題:
用一千萬個標誌位表示對應數字是否為素數,剛開始時將其全部置為true,代表是素數。
然後進行篩選:2的倍數全部不是素數,將2的倍數變成false,3的倍數全都不是素數,將3的倍數變成false,4的倍數全都不是素數,將4的倍數變成false.。。。。
最後計算true的值就行了
優化:既然偶數全都不是素數,那就不用設定標誌位來設定他們了,這樣可以將標誌位佔用的記憶體大小減少一半
使用bit作為標誌位,而不是bool,這樣可以將記憶體使用量將為原來的1/8
/* 特色: 1.利用篩法,但是取消了對偶數位的儲存,例如記憶體中第一位是1,第二位是3,第三位是5 2.利用位(bit)作為儲存位置,而不是基本資料型別,節省記憶體 3.程式一開始就將所有素數找出,後續步驟只不過是:輸入-計數-輸出 而已 */ #include<iostream> #include<string.h> #define Length 10000001 using std::cin; using std::cout; using std::endl; //將a的des位置為1 inline void set(char* a, int des) { char &op = a[des/8]; int offset = des % 8;//0-7 char tmp = 1; tmp = tmp << (7-offset); op = op | tmp; } int main() { int num = 5000000 / 8 + 1; char *a = new char[num]; memset(a, 0, num); for (int i = 3; i < (Length-1)/2; i += 2) for (int j = 3; (i*j - 1) / 2 < (Length-1)/2; j += 2) set(a, (i*j - 1) / 2); int n; while (cin >> n && n != 0) { if (n == 1){ cout << "0" << endl; continue; } else if (n == 2){ cout << "1" << endl; continue; } if (n % 2 == 0) n--; n = (n - 1) / 2; int count = 2; for (int i = 2; i <= n; i++) { if ((a[i / 8] & (1 << (7 - i % 8))) == 0)//為0的奇數位是素數 count++; } cout << count << endl; } }