傳送門
https://pintia.cn/problem-sets/994805260223102976/problems/994805309963354112
題目
令Pi表示第i個素數。現任給兩個正整數M <= N <= 104,請輸出PM到PN的所有素數。
輸入格式:
輸入在一行中給出M和N,其間以空格分隔。
輸出格式:
輸出從PM到PN的所有素數,每10個數字占1行,其間以空格分隔,但行末不得有多余空格。
輸入樣例:
5 27
輸出樣例:
11 13 17 19 23 29 31 37 41 43
47 53 59 61 67 71 73 79 83 89
97 101 103
分析
此題困擾了時間還蠻長的,主要就是效率問題,要在100ms內求出第10000個以內的素數,這與求10000以內的素數的計算次數完全不同。我是在參考了別人的代碼后才寫出來的,還考慮了好久算法的問題,發現了一個規律:一個數,只要它不是素數(質數),那么它肯定至少有一個因子是素數。這個規律我沒法去證明,但是還沒有發現反例,我就默認這個規律是成立的,然后就有了判斷素數的方法isPrimeNumber。
另外值得注意的是,如果你判斷n是不是素數,只要判斷到√n即可,因為再讓其中的一個因子遞增,那么另一個因子一定會遞減,又與之前的數值重復了,故無需再次判斷。
具體算法見函數即可。
源代碼
//C/C++實現
#include <stdio.h>
#include <iostream>
using namespace std;
int PNarray[10000] = {2}; //PNarray[0] = 2;
bool isPrimeNumber(int n, int PNarray[]){
for(int i = 0; PNarray[i] * PNarray[i] <= n; i++){
if(n % PNarray[i] == 0){
return false;
}
}
return true;
}
int main(){
int a, b;
scanf("%d %d", &a, &b);
int index = 1;
for(int i = 3; index < b; i += 2){ //建立到第b個數的素數表
if(isPrimeNumber(i, PNarray)){ //is prime number
PNarray[index++] = i; //store in prime number table
}
}
int count = 0;
for(int j = a - 1; j < b; j++){
if(count % 10 != 0){
printf("%c", ' ');
}
printf("%d", PNarray[j]);
count++;
if(count % 10 == 0){
printf("%c", '\n');
}
}
if(count % 10 != 0){
printf("%c", '\n');
}
return 0;
}