1. 程式人生 > >HDOJ1431 素數迴文 --- 快速素數篩+打表

HDOJ1431 素數迴文 --- 快速素數篩+打表

Problem Description  xiaoou33對既是素數又是迴文的數特別感興趣。比如說151既是素數又是個迴文。現在xiaoou333想要你幫助他找出某個範圍內的素數迴文數,請你寫個程式找出 a 跟b 之間滿足條件的數。(5 <= a < b <= 100,000,000);

Input  這裡有許多組資料,每組包括兩組資料a跟b。

Output  對每一組資料,按從小到大輸出a,b之間所有滿足條件的素數迴文數(包括a跟b)每組資料之後空一行。

Sample Input

5 500

Sample Output

5  7  11  101  131  151  181  191  313  353  373  383  

因為要在大範圍內查詢素數,所以採用快速素數篩,迴文數的話直接手動轉置判斷是否和原來的數相等就可以了。

因為給定的範圍大,直接做會超時,所以先在本地算出結果觀察規律。

最後發現1億以內的迴文素數最大為9989899,不到1千萬,相當於9989899以後的數都不用判斷了,瞬間資料規模就下降了一個指數級。

用flag陣列來標記迴文素數,先素數篩,false表示是素數,然後在素數中判斷迴文,如果不是迴文,標記改為true.

這樣flag陣列中標記為false的就是迴文素數。(當然也可以直接把本地跑出來的結果放在數組裡打表)

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
bool flag[9989900];// false表示是素數

// 素數篩
void Init() {
    memset(flag,0,sizeof(flag));
    for(int i = 2;i <= 9989899;i++) {
         if(flag[i] == false) {
             for(int j = 2*i;j <= 9989899;j += i) {
                 flag[j] = true;
             }
         }
    }
}

// 判斷x是否是迴文數
bool IsPalindrome(int x) {
    int temp = x;
    int ret = 0;
    while(x) {
        ret = ret * 10 + x % 10;
        x /= 10;
    }
    if(ret == temp) return true;
    return false;
}

int main()
{
    Init();
    for(int i = 1;i <= 9989899;i++) {
        if(flag[i] == true)
            continue;
        if(!IsPalindrome(i))    
            flag[i] = true;
    }
    int a,b;
    while(scanf("%d%d",&a,&b) != EOF) {
        if(b > 9989899) b = 9989899;
        for(int i = a;i <= b;i++) {
            if(flag[i] == false)
                printf("%d\n",i);
        }
        printf("\n");
    }
    
    return 0;
}